Initial commit

This commit is contained in:
Pascal Engélibert 2022-09-19 18:41:09 +02:00
commit 05cd190c53
Signed by: tuxmain
GPG Key ID: 3504BC6D362F7DCA
155 changed files with 49378 additions and 0 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/public

7
.vscode/settings.json vendored Normal file
View File

@ -0,0 +1,7 @@
{
"spellright.language": [],
"spellright.documentTypes": [
"latex",
"plaintext"
]
}

13
README.md Normal file
View File

@ -0,0 +1,13 @@
# txmn.tk website
Sources for my personal website [txmn.tk](https://txmn.tk).
## Build
Use [zola](https://getzola.org).
## License
CopyLeft 2022 Pascal Engélibert
This work (website's source code and content, except some contents, logos and libraries) is licensed under a [Creative Commons Attribution-ShareAlike 4.0 International License](https://creativecommons.org/licenses/by-sa/4.0/). (CC BY-SA)

43
config.toml Normal file
View File

@ -0,0 +1,43 @@
base_url = "/"
compile_sass = true
build_search_index = false
default_language = "en"
minify_html = false
[slugify]
paths = "off"
taxonomies = "off"
[markdown]
highlight_code = true
[extra]
sitename = "tuxmain's homepage"
[languages.eo]
generate_feed = true
taxonomies = [
{name = "tags"},
]
[languages.eo.translations]
[languages.en]
generate_feed = true
taxonomies = [
{name = "tags"},
]
[languages.en.translations]
[languages.fr]
generate_feed = true
taxonomies = [
{name = "tags"},
]
[languages.fr.translations]

123
content/_index.eo.md Normal file
View File

@ -0,0 +1,123 @@
+++
title = "Hejmo"
insert_anchor_links = "left"
+++
<div class="service_boxes">
{{ service_box(href="https://flim.txmn.tk", title="PeerTube", img="/img/peertube.svg", img_alt="Logotipo PeerTube") }}
{{ service_box(href="/framadate", title="Framadate", img="/img/framadate.png", img_alt="Logotipo Framadate") }}
{{ service_box(href="/element", title="Matrix / Element", img="/img/element.svg", img_alt="Logotipo Element") }}
{{ service_box(href="https://forum.progaccess.net", title="Forumo ProgAccess", img="/img/progaccess.png", img_alt="Logotipo ProgAccess") }}
{{ service_box(href="https://cloud.txmn.tk", title="NextCloud", img="/img/nextcloud.svg", img_alt="Logotipo NextCloud") }}
{{ service_box(href="/lufi", title="Lufi", img="/img/lufi.svg", img_alt="Logotipo Lufi") }}
{{ service_box(href="/lutim", title="Lutim", img="/img/lutim.png", img_alt="Logotipo Lutim") }}
{{ service_box(href="/l", title="LSTU", img="/img/lstu.svg", img_alt="Logotipo LSTU") }}
{{ service_box(href="https://pad.txmn.tk", title="Etherpad", img="/img/etherpad.png", img_alt="Logotipo Etherpad") }}
{{ service_box(href="/mumble", title="Mumble", img="/img/mumble.svg", img_alt="Logotipo Mumble") }}
</div>
**[Artikoloj de blogo](blog)**
## Kiu li estas? {#kiu}
* Homo ĝis pruvita alie;
* Pascal Engélibert;
* Programisto liberecista, studento de matematiko;
* Rust, Python, PHP, web, franca, angla, hispana, esperanta;
* Preferas tabojn;
* Preferas [GNU AGPL](https://www.gnu.org/licenses/licenses.html#AGPL) kaj [CC BY-SA](https://creativecommons.org/licenses/by-sa/4.0/).
## Projektoj {#projektoj}
<div class="service_boxes">
{{ service_box(href="https://progaccess.net", title="ProgAccess", img="/img/progaccess.png", img_alt="Logotipo ProgAccess") }}
{{ service_box(href="//zettascript.org/projects/gmixer/", title="ĞMixer", img="/img/gmixer.svg", img_alt="Logotipo ĞMixer") }}
{{ service_box(href="https://framagit.org/ZettaScript/syeve", title="Syeve", img="/img/syeve.svg", img_alt="Logotipo Syeve") }}
{{ service_box(href="https://framagit.org/ZettaScript/forceatlas2-rs", title="ForceAtlas2-rs", img="/img/forceatlas2.png", img_alt="Grafo") }}
{{ service_box(href="//worldwotmap.duniter.org", title="WorldWotMap", img="/img/gbreve.svg", img_alt="Ğ") }}
</div>
### Projektoj kreitaj aŭ kunkreitaj {#projektoj2}
* [ProgAccess](https://www.progaccess.net) kaj la retejoj [NVDA-FR](https://www.nvda-fr.org), [AccessiKey](https://accessikey.nvda-fr.org), por alirebligi la komputiko al ĉiu
* [ĞMixer](//zettascript.org/projects/gmixer/), por anonimigi viajn kriptomonajn spezojn tra unu cepa reto
* [WorldWotMap](//worldwotmap.duniter.org), geografia mapo de la reto de fido Duniter
* [ForceAtlas2-rs](https://framagit.org/ZettaScript/forceatlas2-rs), realigo de la algoritmo de grafspacigo ForceAtlas2 en Rust
* [Ğ1force](https://git.duniter.org/tools/g1force), brutfortilo Scrypt+Ed25519 en Rust
* [Syeve](https://framagit.org/ZettaScript/syeve) (Simple yet efficient video encoding), kodeko de video senperda
* [matrix_bridge](https://git.p2p.legal/tuxmain/minetest-matrix_bridge), mod Minetest por diskuti kun Matrix
* [ğexplore](https://git.duniter.org/tools/gexplore), tridimensia esplorilo de reto de fido Duniter
* [Telefono Diskogurdo](https://git.txmn.tk/tuxmain/telephone-jukebox), diska telefono kiu muzikas
### Kontribuoj {#kontribuoj}
* [Libera Mono](https://monnaie-libre.fr): variitaj kontribuoj
* [Wotmap](https://wotmap.duniter.org), bildigi grafon de unu reto de fido Duniter (backend)
* [Duniter](https://git.duniter.org/nodes/rust/duniter-v2s), blokĉeno por libera mono (Rust)
### Etaj kontribuoj {#etaj-kontribuoj}
* GParted: [alirebleco al ekranlegiloj](https://gitlab.gnome.org/GNOME/gparted/-/commit/f31fbb986fab551a4db8c05e9a45720b35bc5385)
* Tera: [multlingva filtrilo `date`](https://github.com/Keats/tera/pull/742)
### Kuriozaj projektoj {#kuriozaj-projektoj}
* [Perkomputile ciferece stirata (CNC) artikigita brako](https://framagit.org/ZettaScript/cnc-arm)
* [Pervarma lasera printilo kun Arduino](https://framagit.org/ZettaScript/laserprinter) (por printi sur papero sen konsumi inkon)
* Multfunkcia sistemo por videkunveno aŭ datumfluo en Rust
* Transformilo de sono al MIDI
## Servoj {#servoj}
* [NextCloud](https://cloud.txmn.tk) à louer en Ğ1 ([plus d'infos](https://www.gchange.fr/#/app/market/view/AW6aQfpXzeWXAkHvSFwJ/compte-nextcloud-stockage-de-fichiers))
* 🗓 [Framadate](/framadate)
* 🎞 [PeerTube Flim](https://flim.txmn.tk)
* 🎧 Servilo Mumble publika: `txmn.tk:64738` &#8211; [Interfaco Mumble TTT](/mumble)
* 🎮 [Juneland](https://juneland.fr): serviloj MineTest por la libera mono
* 🏷 [Viğnette](/g1/vignette): printu etikedojn por viaj ğbazaroj
* [Forumo ProgAccess](https://forum.progaccess.net): interhelpo por la alirebleco de komputiko
* 📁 [Lufi](/lufi): sendu dosierojn ĝis 2GB
* 📷 [Lutim](/lutim): sendu bilgojn ĝis 10MB (ideala por forumoj)
* 🗩 [Servilo Matrix](/element): messagerie instantanée fédérée Matrix (interface Element, chiffrement de bout-en-bout, groupes, etc.)
* [Ğ.ML](//xn--tea.ml): sous-domaines gratuits pour la monnaie libre
* Servilo STUN publika: `stun:txmn.tk:3478`
* [Historique des données géographiques Cesium+ de la Ğ1](/g1/history/cesiumplusmap)
* Hébergement/installation de site/blog/boutique Odoo, WordPress, ou autres. Payable en Ğ1, me contacter par e-mail.
* 🗒 [Etherpad](https://pad.txmn.tk): document partagé de prise de notes en temps réel
## Ankaŭ gastigas {#gastigas}
<div class="service_boxes">
{{ service_box(href="//dubitaristes.fr", title="Les Dubitaristes Girondins", img="/img/dubitaristes.png", img_alt="Logotipo Dubitaristes") }}
{{ service_box(href="https://collectifsources.fr", title="Collectif Sources", img="/img/collectifsources.png", img_alt="Logo Collectif Sources") }}
{{ service_box(href="//juneland.fr", title="Juneland", img="/img/minetest.svg", img_alt="Logotipo MineTest") }}
</div>
## La kamaradoj {#kamaradoj}
* [Librezo](https://librezo.com) helpas la profesiulojn liberiĝi de la GAFAM per instali siajn proprajn komputikajn servojn.
## Kontaktoj {#kontaktoj}
* Retpoŝto: `t ĉe txmn punkto tk` _aŭ_ `tuxmain ĉe zettascript punkto org`
* [Publika ŝlosilo GPG](/tuxmain.asc)
* <a rel="author" href="https://toot.aquilenet.fr/@tuxmain">Mastodon</a>
* [Kontaktformularo ZettaScript](//zettascript.org/contact.php)
* [Libera Mono Ğ1](https://demo.cesium.app/#/app/wot/45GfjkWCWQhJ3epJVGC2NSg1Rcu4Ue1vDD3kk9eLs5TQ/) (publika ŝlosilo: `45GfjkWCWQhJ3epJVGC2NSg1Rcu4Ue1vDD3kk9eLs5TQ:CUw`)
* [GitLab Framagit](https://framagit.org/ZettaScript) (projektoj)
* [GitLab Duniter](https://git.duniter.org/tuxmain) (projektoj pri la libera mono)
* [Gitea P2P.legal](https://git.p2p.legal/tuxmain) (aliaj projektoj pri la libera mono)
* [Gitea JSB](https://gitea.jeunes-science.asso.fr/tuxmain) (projektoj [Jeunes-Science Bordeaux](https://jeunes-science.asso.fr))
* [Gitxmn](https://git.txmn.tk/tuxmain) (etaj projektoj kiuj mi ne sciis kien publikigi)
* [GitLab Gnome](https://gitlab.gnome.org/tuxmain)
* [GitHub](https://github.com/ZettaScript) (malpreferata)
<a href="https://liberapay.com/tuxmain/donate" title="Doni kun Liberapay"><img alt="Doni kun Liberapay" src="/img/liberapay-donate.svg"/></a>
## Pri {#pri}
🦀 Retejo generita kun [zola](https://www.getzola.org/).
🧮 Gastigata sur unu Raspberry Pi en Bègles, apud Bordeaux, en Franco.
📜 Ĉi tiu retejo estas publikigita laŭ la permesilo <a rel="license" href="//creativecommons.org/licenses/by-sa/4.0/">CC BY-SA 4.0</a>. ([Fontkodo](https://git.txmn.tk/tuxmain/website)) [Kondiĉoj de uzo](@/eula.eo.md)

123
content/_index.fr.md Normal file
View File

@ -0,0 +1,123 @@
+++
title = "Accueil"
insert_anchor_links = "left"
+++
<div class="service_boxes">
{{ service_box(href="https://flim.txmn.tk", title="PeerTube", img="/img/peertube.svg", img_alt="Logo PeerTube") }}
{{ service_box(href="/framadate", title="Framadate", img="/img/framadate.png", img_alt="Logo Framadate") }}
{{ service_box(href="/element", title="Matrix / Element", img="/img/element.svg", img_alt="Logo Element") }}
{{ service_box(href="https://forum.progaccess.net", title="Forum ProgAccess", img="/img/progaccess.png", img_alt="Logo ProgAccess") }}
{{ service_box(href="https://cloud.txmn.tk", title="NextCloud", img="/img/nextcloud.svg", img_alt="Logo NextCloud") }}
{{ service_box(href="/lufi", title="Lufi", img="/img/lufi.svg", img_alt="Logo Lufi") }}
{{ service_box(href="/lutim", title="Lutim", img="/img/lutim.png", img_alt="Logo Lutim") }}
{{ service_box(href="/l", title="LSTU", img="/img/lstu.svg", img_alt="Logo LSTU") }}
{{ service_box(href="https://pad.txmn.tk", title="Etherpad", img="/img/etherpad.png", img_alt="Logo Etherpad") }}
{{ service_box(href="/mumble", title="Mumble", img="/img/mumble.svg", img_alt="Logo Mumble") }}
</div>
**[Articles de blog](blog)**
## Qui est-ce&#8239;? {#qui}
* Être humain jusqu'à preuve du contraire&#8239;;
* Pascal Engélibert&#8239;;
* Développeur libriste, étudiant en mathématiques&#8239;;
* Rust, Python, PHP, web, français, anglais, espagnol, espéranto&#8239;;
* Préfère les tabulations&#8239;;
* Préfère [GNU AGPL](https://www.gnu.org/licenses/licenses.html#AGPL) et [CC BY-SA](https://creativecommons.org/licenses/by-sa/4.0/).
## Projets {#projets}
<div class="service_boxes">
{{ service_box(href="https://progaccess.net", title="ProgAccess", img="/img/progaccess.png", img_alt="Logo ProgAccess") }}
{{ service_box(href="//zettascript.org/projects/gmixer/", title="ĞMixer", img="/img/gmixer.svg", img_alt="Logo ĞMixer") }}
{{ service_box(href="https://framagit.org/ZettaScript/syeve", title="Syeve", img="/img/syeve.svg", img_alt="Logo Syeve") }}
{{ service_box(href="https://framagit.org/ZettaScript/forceatlas2-rs", title="ForceAtlas2-rs", img="/img/forceatlas2.png", img_alt="Graphe") }}
{{ service_box(href="//worldwotmap.duniter.org", title="WorldWotMap", img="/img/gbreve.svg", img_alt="Ğ") }}
</div>
### Projets créés ou cocréés {#projets2}
* [ProgAccess](https://www.progaccess.net) et les sites [NVDA-FR](https://www.nvda-fr.org), [AccessiKey](https://accessikey.nvda-fr.org), pour rendre l'informatique accessible aux mal ou non voyant·es
* [ĞMixer](//zettascript.org/projects/gmixer/), pour anonymiser vos transactions de cryptomonnaie à travers un réseau en oignons
* [WorldWotMap](//worldwotmap.duniter.org), pour voir la carte géographique d'une Toile de Confiance Duniter
* [ForceAtlas2-rs](https://framagit.org/ZettaScript/forceatlas2-rs), implémentation de l'algo de positionnement de graphe ForceAtlas2 en Rust
* [Ğ1force](https://git.duniter.org/tools/g1force), outil de bruteforce Scrypt+Ed25519 en Rust
* [Syeve](https://framagit.org/ZettaScript/syeve) (Simple yet efficient video encoding), codec lossless en Rust
* [matrix_bridge](https://git.p2p.legal/tuxmain/minetest-matrix_bridge), mod Minetest pour l'interaction avec Matrix
* [ğexplore](https://git.duniter.org/tools/gexplore), un explorateur en 3D de toile de confiance Duniter
* [Téléphone Jukebox](https://git.txmn.tk/tuxmain/telephone-jukebox), un téléphone à cadran jouant des sons
### Contributions {#contributions}
* [Monnaie Libre](https://monnaie-libre.fr)&nbsp;: contributions éparses et variées
* [Wotmap](https://wotmap.duniter.org), représenter le graphe d'une toile de confiance Duniter (développement du backend)
* [Duniter](https://git.duniter.org/nodes/rust/duniter-v2s), blockchain pour monnaie libre (Rust)
### Micro-contributions {#micro-contributions}
* GParted&nbsp;: [accessibilité aux lecteurs d'écran](https://gitlab.gnome.org/GNOME/gparted/-/commit/f31fbb986fab551a4db8c05e9a45720b35bc5385)
* Tera&nbsp;: [support de la langue pour le filtre `date`](https://github.com/Keats/tera/pull/742)
### Bidouillages en cours {#bidouillages}
* [Bras articulé CNC modulaire imprimé en 3D, contrôlé par Arduino](https://framagit.org/ZettaScript/cnc-arm)
* [Imprimante thermique LASER Arduino](https://framagit.org/ZettaScript/laserprinter) (pour imprimer sur papier sans consommer d'encre)
* Système super-modulaire de visioconférence/stream/live en Rust
* Convertisseur audio vers MIDI
## Services {#services}
* [NextCloud](https://cloud.txmn.tk) à louer en Ğ1 ([plus d'infos](https://www.gchange.fr/#/app/market/view/AW6aQfpXzeWXAkHvSFwJ/compte-nextcloud-stockage-de-fichiers))
* 🗓 [Framadate](/framadate)
* 🎞 [PeerTube Flim](https://flim.txmn.tk)
* 🎧 Serveur Mumble public&nbsp;: `txmn.tk:64738` &#8211; [Interface Mumble web](/mumble)
* 🎮 [Juneland](https://juneland.fr)&nbsp;: serveurs MineTest pour la monnaie libre
* 🏷 [Viğnette](/g1/vignette) à imprimer pour vos ğmarchés
* [Forum ProgAccess](https://forum.progaccess.net)&nbsp;: entraide pour l'accessibilité de l'informatique
* 📁 [Lufi](/lufi)&nbsp;: envoi de fichiers gratuit jusqu'à 2Go
* 📷 [Lutim](/lutim)&nbsp;: envoi d'images gratuit jusqu'à 10Mo (pratique pour les forums)
* 🗩 [Serveur Matrix](/element)&nbsp;: Messagerie instantanée fédérée Matrix (interface Element, chiffrement de bout-en-bout, groupes, etc.)
* [Ğ.ML](//xn--tea.ml)&nbsp;: sous-domaines gratuits pour la monnaie libre
* Serveur STUN public&nbsp;: `stun:txmn.tk:3478`
* [Historique des données géographiques Cesium+ de la Ğ1](/g1/history/cesiumplusmap)
* Hébergement/installation de site/blog/boutique Odoo, WordPress, ou autres. Payable en Ğ1, me contacter par e-mail.
* 🗒 [Etherpad](https://pad.txmn.tk)&nbsp;: document partagé de prise de notes en temps réel
## Héberge aussi {#heberge}
<div class="service_boxes">
{{ service_box(href="//dubitaristes.fr", title="Les Dubitaristes Girondins", img="/img/dubitaristes.png", img_alt="Logo Dubitaristes") }}
{{ service_box(href="https://collectifsources.fr", title="Collectif Sources", img="/img/collectifsources.png", img_alt="Logo Collectif Sources") }}
{{ service_box(href="//juneland.fr", title="Juneland", img="/img/minetest.svg", img_alt="Logo MineTest") }}
</div>
## Les camarades {#camarades}
* [Librezo](https://librezo.com) aide les pros à se libérer des GAFAM en installant chez vous votre infrastructure informatique.
## Contacts {#contacts}
* Courrier électronique&nbsp;: `t chez txmn point tk` _ou_ `tuxmain chez zettascript point org`
* [Clé publique GPG](/tuxmain.asc)
* <a rel="author" href="https://toot.aquilenet.fr/@tuxmain">Mastodon</a>
* [Formulaire de contact ZettaScript](//zettascript.org/contact.php)
* [Monnaie Libre Ğ1](https://demo.cesium.app/#/app/wot/45GfjkWCWQhJ3epJVGC2NSg1Rcu4Ue1vDD3kk9eLs5TQ/) (clé publique&nbsp;: `45GfjkWCWQhJ3epJVGC2NSg1Rcu4Ue1vDD3kk9eLs5TQ:CUw`)
* [GitLab Framagit](https://framagit.org/ZettaScript) (projets en général)
* [GitLab Duniter](https://git.duniter.org/tuxmain) (projets pour la monnaie libre)
* [Gitea P2P.legal](https://git.p2p.legal/tuxmain) (autres projets pour la monnaie libre)
* [Gitea JSB](https://gitea.jeunes-science.asso.fr/tuxmain) (projets [Jeunes-Science Bordeaux](https://jeunes-science.asso.fr))
* [Gitxmn](https://git.txmn.tk/tuxmain) (petits projets que je ne savais pas où mettre)
* [GitLab Gnome](https://gitlab.gnome.org/tuxmain)
* [GitHub](https://github.com/ZettaScript) (déprécié, conservé pour la rétrocompatibilité seulement)
<a href="https://liberapay.com/tuxmain/donate" title="Donner avec Liberapay"><img alt="Donner avec Liberapay" src="/img/liberapay-donate.svg"/></a>
## À propos {#a-propos}
🦀 Site généré avec [zola](https://www.getzola.org/).
🧮 Hébergé sur un Raspberry Pi à Bègles, près de Bordeaux, en France.
📜 Ce site est mis à disposition selon les termes de la licence <a rel="license" href="//creativecommons.org/licenses/by-sa/4.0/">CC BY-SA 4.0</a>. ([Code source](https://git.txmn.tk/tuxmain/website)) [CGU](@/eula.fr.md)

125
content/_index.md Normal file
View File

@ -0,0 +1,125 @@
+++
title = "Home"
insert_anchor_links = "left"
+++
<div class="service_boxes">
{{ service_box(href="https://flim.txmn.tk", title="PeerTube", img="/img/peertube.svg", img_alt="Logo PeerTube") }}
{{ service_box(href="/framadate", title="Framadate", img="/img/framadate.png", img_alt="Logo Framadate") }}
{{ service_box(href="/element", title="Matrix / Element", img="/img/element.svg", img_alt="Logo Element") }}
{{ service_box(href="https://forum.progaccess.net", title="Forum ProgAccess", img="/img/progaccess.png", img_alt="Logo ProgAccess") }}
{{ service_box(href="https://cloud.txmn.tk", title="NextCloud", img="/img/nextcloud.svg", img_alt="Logo NextCloud") }}
{{ service_box(href="/lufi", title="Lufi", img="/img/lufi.svg", img_alt="Logo Lufi") }}
{{ service_box(href="/lutim", title="Lutim", img="/img/lutim.png", img_alt="Logo Lutim") }}
{{ service_box(href="/l", title="LSTU", img="/img/lstu.svg", img_alt="Logo LSTU") }}
{{ service_box(href="https://pad.txmn.tk", title="Etherpad", img="/img/etherpad.png", img_alt="Logo Etherpad") }}
{{ service_box(href="/mumble", title="Mumble", img="/img/mumble.svg", img_alt="Logo Mumble") }}
</div>
**[Blog articles](blog)**
## Who is that? {#who}
* Human being until proven otherwise;
* Pascal Engélibert;
* Libre developper, student of mathematics;
* Rust, Python, PHP, web, French, English, Spanish, Esperanto;
* Prefers tabulations;
* Prefers [GNU AGPL](https://www.gnu.org/licenses/licenses.html#AGPL) and [CC BY-SA](https://creativecommons.org/licenses/by-sa/4.0/).
## Projects {#projects}
<div class="service_boxes">
{{ service_box(href="https://progaccess.net", title="ProgAccess", img="/img/progaccess.png", img_alt="Logo ProgAccess") }}
{{ service_box(href="//zettascript.org/projects/gmixer/", title="ĞMixer", img="/img/gmixer.svg", img_alt="Logo ĞMixer") }}
{{ service_box(href="https://framagit.org/ZettaScript/syeve", title="Syeve", img="/img/syeve.svg", img_alt="Logo Syeve") }}
{{ service_box(href="https://framagit.org/ZettaScript/forceatlas2-rs", title="ForceAtlas2-rs", img="/img/forceatlas2.png", img_alt="Graph") }}
{{ service_box(href="//worldwotmap.duniter.org", title="WorldWotMap", img="/img/gbreve.svg", img_alt="Ğ") }}
</div>
### Projects created or cocreated {#projects2}
* [ProgAccess](https://www.progaccess.net) and the sites [NVDA-FR](https://www.nvda-fr.org), [AccessiKey](https://accessikey.nvda-fr.org), to make computers accessible to the visually impaired
* [ĞMixer](//zettascript.org/projects/gmixer/), to anonymize your cryptocurrency transactions through an onion network
* [WorldWotMap](//worldwotmap.duniter.org), a geographical map of a Duniter web of trust
* [ForceAtlas2-rs](https://framagit.org/ZettaScript/forceatlas2-rs), implementation of the graph layout ForceAtlas2 in Rust
* [Ğ1force](https://git.duniter.org/tools/g1force), Scrypt+Ed25519 bruteforce tool in Rust
* [Syeve](https://framagit.org/ZettaScript/syeve) (Simple yet efficient video encoding), lossless codec in Rust
* [matrix_bridge](https://git.p2p.legal/tuxmain/minetest-matrix_bridge), Minetest mod for Matrix messaging interaction
* [ğexplore](https://git.duniter.org/tools/gexplore), a 3D web of trust history explorer for Duniter
* [Jukebox Telephone](https://git.txmn.tk/tuxmain/telephone-jukebox), a dial phone that plays sounds
### Contributions {#contributions}
* [Libre Currency](https://monnaie-libre.fr): sparse and various contributions
* [Wotmap](https://wotmap.duniter.org), represent the graph of a Duniter web of trust (backend development)
* [Duniter](https://git.duniter.org/nodes/rust/duniter-v2s), blockchain for libre currency (Rust)
### Micro-contributions {#micro-contributions}
* GParted: [screen reader accessibility](https://gitlab.gnome.org/GNOME/gparted/-/commit/f31fbb986fab551a4db8c05e9a45720b35bc5385)
* Tera: [`date` filter supports localization](https://github.com/Keats/tera/pull/742)
### WiP Hacks {#hacks}
* [Modular articulated arm CNC, 3D-printed, controled by Arduino](https://framagit.org/ZettaScript/cnc-arm)
* [LASER thermal printer with Arduino](https://framagit.org/ZettaScript/laserprinter) (for printing on paper without consuming ink)
* Super-modular visioconference/stream/live system in Rust
* Audio to MIDI converter
## Services {#services}
* [NextCloud](https://cloud.txmn.tk) to rent in Ğ1 ([more info](https://www.gchange.fr/#/app/market/view/AW6aQfpXzeWXAkHvSFwJ/compte-nextcloud-stockage-de-fichiers))
* 🗓 [Framadate](/framadate)
* 🎞 [PeerTube Flim](https://flim.txmn.tk)
* 🎧 Public Mumble server: `txmn.tk:64738` &#8211; [Mumble web interface](/mumble)
* 🎮 [Juneland](https://juneland.fr): MineTest servers for the libre currency
* 🏷 [Viğnette](/g1/vignette) to print labels for your ğmarkets
* [Forum ProgAccess](https://forum.progaccess.net): mutual aid for computer accessibility
* 📁 [Lufi](/lufi): free file sharing up to 2GB
* 📷 [Lutim](/lutim): free image sharing up to 10MB (convenient for forums)
* 🗩 [Matrix server](/element): Federated instant messaging Matrix (Element interface, end-to-end encryption, groups, etc.)
* [Ğ.ML](//xn--tea.ml): free subdomains for the libre currency
* Public STUN server: `stun:txmn.tk:3478`
* [Cesium+ geographical data history of Ğ1](/g1/history/cesiumplusmap)
* Hosting/installation of site/blog/shop Odoo, WordPress, or other. Paid in Ğ1, contact me by email.
* 🗒 [Etherpad](https://pad.txmn.tk): Real time shared document for note taking
## Also hosting {#host}
<div class="service_boxes">
{{ service_box(href="//dubitaristes.fr", title="Les Dubitaristes Girondins", img="/img/dubitaristes.png", img_alt="Logo Dubitaristes") }}
{{ service_box(href="https://collectifsources.fr", title="Collectif Sources", img="/img/collectifsources.png", img_alt="Logo Collectif Sources") }}
{{ service_box(href="//juneland.fr", title="Juneland", img="/img/minetest.svg", img_alt="Logo MineTest") }}
</div>
## The camarades {#camarades}
* [Librezo](https://librezo.com) helps the professionals to liberate themselves from the GAFAM by installing your own computing services.
## Contacts {#contacts}
* Electronic missive: `t åt txmn døt tk` _or_ `tuxmain åt zettascript døt org`
* [GPG public key](/tuxmain.asc)
* <a rel="author" href="https://toot.aquilenet.fr/@tuxmain">Mastodon</a>
* [ZettaScript contact form](//zettascript.org/contact.php)
* [Libre Currency Ğ1](https://demo.cesium.app/#/app/wot/45GfjkWCWQhJ3epJVGC2NSg1Rcu4Ue1vDD3kk9eLs5TQ/) (pubkey: `45GfjkWCWQhJ3epJVGC2NSg1Rcu4Ue1vDD3kk9eLs5TQ:CUw`)
* [GitLab Framagit](https://framagit.org/ZettaScript) (projects in general)
* [GitLab Duniter](https://git.duniter.org/tuxmain) (projects about libre currency)
* [Gitea P2P.legal](https://git.p2p.legal/tuxmain) (also projects about libre currency)
* [Gitea JSB](https://gitea.jeunes-science.asso.fr/tuxmain) (projects about [Jeunes-Science Bordeaux](https://jeunes-science.asso.fr))
* [Gitxmn](https://git.txmn.tk/tuxmain) (small projects I didn't know where to publish)
* [GitLab Gnome](https://gitlab.gnome.org/tuxmain)
* [GitHub](https://github.com/ZettaScript) (deprecated, used for backward compatibility only)
<a href="https://liberapay.com/tuxmain/donate" title="Donate with Liberapay"><img alt="Donate with Liberapay" src="/img/liberapay-donate.svg"/></a>
## About {#about}
🦀 Site generated with [zola](https://www.getzola.org/).
🧮 Hosted on a Raspberry Pi in Bègles, near Bordeaux, France.
📜 This website is published under the terms of the <a rel="license" href="//creativecommons.org/licenses/by-sa/4.0/">CC BY-SA 4.0</a> license. ([Source code](https://git.txmn.tk/tuxmain/website)) ([EULA](@/eula.md))
<a class="hidden" href="/admin">admin</a>

View File

@ -0,0 +1,6 @@
+++
page_template = "blog.html"
title = "Blogo"
sort_by = "date"
insert_anchors = "right"
+++

View File

@ -0,0 +1,6 @@
+++
page_template = "blog.html"
title = "Blog"
sort_by = "date"
insert_anchors = "right"
+++

6
content/blog/_index.md Normal file
View File

@ -0,0 +1,6 @@
+++
page_template = "blog.html"
title = "Blog"
sort_by = "date"
insert_anchors = "right"
+++

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

View File

@ -0,0 +1,64 @@
+++
title = "Aŭtonoma Atmega328P, paŝ-paŝe"
date = 2022-09-12
description = "Facila gvido por programi aŭtonoman Atmega328P-on kun Arduino."
[taxonomies]
tags = ["elektroniko", "Arduino"]
+++
Ĉi tiu gvido priskribas kiel programi aŭtonoman mikrokontrolilon Atmega328P uzante karton Arduino, kaj exteran oscilatoron je 16MHz. Ĝi rezultas el mia frustro kaŭzita de ĉiuj miaj malsukcesaj provoj, kaj de legoj de malkompletaj instruiloj. Nun mi trovis funkciantan metodon, mi ĝin publikigas tie por ne perdi ĝin.
## Necesa aparataro
* Atmega328P (la "P" gravas)
* karto Arduino (mi uzis unu Arduino Micro)
* oscilatoro 16MHz
* 2× kondensiloj 22pF
* rezistilo 10kΩ
* kondensilo 100µF
### Komento
Se vi ne havas kondensilon je 22pF, vi povas trovi iujn en malnovaj aparatoj (ekzemple, videosurbendigiloj enhavas multan). Malfeliĉe la trairantaj kondensiloj je tiu valoro ŝajne malabundas, do vi eble devos malveldi multajn surfacajn kondensilojn kaj trovi la bonaj uzante unu [simpla ]
Si vous n'avez aucun condensateur de 22pF, vous pouvez en récupérer dans un vieil appareil (par exemple il y en a plein dans les magnétoscopes). Malheureusement les condensateurs traversants de cette valeur ont l'air assez rares, donc vous devrez peut-être récupérer plein de condensateurs montés en surface et trouver les bons en fabriquant un [capacimètre tout simple avec une Arduino](https://www.instructables.com/Capacitance-Meter/).
## Circuit
{{ float_img(alt="Circuit for programming the Atmega using an Arduino.", src="circuit.png", style="max-height:100vh;max-width:100%;") }}
La description des broches de l'Atmega328P peut être trouvée dans [sa fiche technique](atmega328p.pdf).
* Connectez les broches MOSI, MISO, SCK(=SCLK) de l'Arduino aux broches correspondantes de l'Atmega. (sur l'Arduino Uno, ce sont respectivement les broches 11, 12, 13)
* Connectez la broche 10 de l'Arduino à la broche Reset de l'Atmega.
* Connectez les deux pôles de l'oscillateur aux broches XTAL/TOSC de l'Atmega, et placez un condensateur de 22pF entre ces pôles et le GND.
* Connectez les GNDs. Connectez les VCC de l'Atmega, AVCC de l'Atmega et +5V de l'Arduino.
Vérifiez bien les branchements. Le MOSI va sur le MOSI et le MISO sur le MISO, ils ne sont pas échangés.
### En production
Les branchements suivants sont nécessaires seulement quand le microcontrôleur n'est pas connecté à l'Arduino.
* Placez une résistance pull-up sur Reset (une résistance de 10kΩ entre Reset et VCC).
* Placez un condensateur de 100µF entre GND et VCC.
* L'oscillateur et les petits condensateurs sont toujours nécessaires.
* VCC et AVCC doivent toujours être reliés.
## Programmation
J'utilise l'IDE Arduino.
D'abord, programmons l'Arduino pour en faire une sorte de relais entre l'ordinateur et le microcontrôleur&nbsp;:
1. Ouvrez le programme d'exemple `ArduinoISP`.
1. Si vous utilisez une Arduino Uno, décommentez la ligne `#define USE_OLD_STYLE_WIRING`.
1. Choisissez votre carte dans le _Type de carte_ (_Arduino Micro_ pour moi).
1. Choisissez votre programmateur habituel (en général _AVR ISP_).
1. Envoyez le programme normalement.
Nous pouvons enfin programmer le microcontrôleur&nbsp;:
1. Ouvrez le programme voulu. (ou testez avec l'exemple `Blink`)
1. Choisissez le type de carte _Arduino Uno_. (même si vous utilisez une autre carte comme programmateur&#8239;; c'est parce qu'un Atmega328P seul avec un oscillateur 16MHz se comporte comme une Arduino Uno)
1. Choisissez le programmateur _Arduino as ISP_.
1. Si le microcontrôleur ne contient pas encore de bootloader, faites _Outils -> Graver la séquence d'initialisation_.
1. Envoyez le programme avec _Croquis -> Téléverser avec un programmateur_.

View File

@ -0,0 +1,62 @@
+++
title = "Atmega328P indépendant, pas à pas"
date = 2022-09-12
description = "Guide simple pour programmer un Atmega328P indépendant avec une Arduino"
[taxonomies]
tags = ["électronique", "Arduino"]
+++
Ce guide décrit comment programmer un microcontrôleur Atmega328P en utilisant une carte Arduino comme programmateur, et un oscillateur 16MHz externe. Il est le résultat de la frustration qu'ont provoqué chez moi toutes les tentatives infructueuses et les lectures de tutoriels incomplets. Maintenant que j'ai trouvé une méthode qui marche, je la publie ici afin de ne pas la perdre.
## Matériel nécessaire
* Atmega328P (le P change tout)
* Arduino board (j'ai utilisé une Arduino Micro)
* oscillateur 16MHz
* 2× condensateur 22pF
* résistance 10kΩ
* condensateur 100µF
### Note
Si vous n'avez aucun condensateur de 22pF, vous pouvez en récupérer dans un vieil appareil (par exemple il y en a plein dans les magnétoscopes). Malheureusement les condensateurs traversants de cette valeur ont l'air assez rares, donc vous devrez peut-être récupérer plein de condensateurs montés en surface et trouver les bons en fabriquant un [capacimètre tout simple avec une Arduino](https://www.instructables.com/Capacitance-Meter/).
## Circuit
{{ float_img(alt="Circuit for programming the Atmega using an Arduino.", src="circuit.png", style="max-height:100vh;max-width:100%;") }}
La description des broches de l'Atmega328P peut être trouvée dans [sa fiche technique](atmega328p.pdf).
* Connectez les broches MOSI, MISO, SCK(=SCLK) de l'Arduino aux broches correspondantes de l'Atmega. (sur l'Arduino Uno, ce sont respectivement les broches 11, 12, 13)
* Connectez la broche 10 de l'Arduino à la broche Reset de l'Atmega.
* Connectez les deux pôles de l'oscillateur aux broches XTAL/TOSC de l'Atmega, et placez un condensateur de 22pF entre ces pôles et le GND.
* Connectez les GNDs. Connectez les VCC de l'Atmega, AVCC de l'Atmega et +5V de l'Arduino.
Vérifiez bien les branchements. Le MOSI va sur le MOSI et le MISO sur le MISO, ils ne sont pas échangés.
### En production
Les branchements suivants sont nécessaires seulement quand le microcontrôleur n'est pas connecté à l'Arduino.
* Placez une résistance pull-up sur Reset (une résistance de 10kΩ entre Reset et VCC).
* Placez un condensateur de 100µF entre GND et VCC.
* L'oscillateur et les petits condensateurs sont toujours nécessaires.
* VCC et AVCC doivent toujours être reliés.
## Programmation
J'utilise l'IDE Arduino.
D'abord, programmons l'Arduino pour en faire une sorte de relais entre l'ordinateur et le microcontrôleur&nbsp;:
1. Ouvrez le programme d'exemple `ArduinoISP`.
1. Si vous utilisez une Arduino Uno, décommentez la ligne `#define USE_OLD_STYLE_WIRING`.
1. Choisissez votre carte dans le _Type de carte_ (_Arduino Micro_ pour moi).
1. Choisissez votre programmateur habituel (en général _AVR ISP_).
1. Envoyez le programme normalement.
Nous pouvons enfin programmer le microcontrôleur&nbsp;:
1. Ouvrez le programme voulu. (ou testez avec l'exemple `Blink`)
1. Choisissez le type de carte _Arduino Uno_. (même si vous utilisez une autre carte comme programmateur&#8239;; c'est parce qu'un Atmega328P seul avec un oscillateur 16MHz se comporte comme une Arduino Uno)
1. Choisissez le programmateur _Arduino as ISP_.
1. Si le microcontrôleur ne contient pas encore de bootloader, faites _Outils -> Graver la séquence d'initialisation_.
1. Envoyez le programme avec _Croquis -> Téléverser avec un programmateur_.

View File

@ -0,0 +1,62 @@
+++
title = "Standalone Atmega328P guide"
date = 2022-09-12
description = "Simple guide to program a standalone Atmega328P using an Arduino."
[taxonomies]
tags = ["electronics", "Arduino"]
+++
This guide describes how to burn a program into an Atmega328P microcontroller, using an Arduino board as programmer and an external 16MHz oscillator. It's the result of the frustration that every single time I wanted to to this, it was a struggle because I couldn't find any _complete_ tutorial. At least, the following works for me.
## Materials needed
* Atmega328P (the P matters)
* Arduino board (I used an Arduino Micro)
* 16MHz oscillator
* 2× 22pF capacitors
* 10kΩ resistor
* 100µF capacitor
### Notes
If you don't have any 22pF capacitor, you can salvage some capacitors from an old device (e.g. there are plenty in videotape readers). Unfortunately through-hole capacitors with this value look pretty rare, so you may need to salvage a bunch of unmarked surface-mounted ones and [build a simple Arduino-based capacitance meter](https://www.instructables.com/Capacitance-Meter/) to find the wanted ones.
## Circuit
{{ float_img(alt="Circuit for programming the Atmega using an Arduino.", src="circuit.png", style="max-height:100vh;max-width:100%;") }}
Check Atmega328P's pinout [in the datasheet](atmega328p.pdf).
* Connect the MOSI, MISO, SCK(=SCLK) pins on the Arduino to the corresponding ones on the Atmega. (on Arduino Uno, they are respectively on pins 11, 12, 13)
* Connect Arduino pin 10 to Atmega's Reset pin.
* Connect each pin on the oscillator to the XTAL/TOSC pins on the Atmega, and place a 22pF capacitor between each of these two pins and the GND.
* Connect the GNDs together. Connect Atmega's VCC, Atmega's AVCC and Arduino's +5V together.
Triple-check the wiring. MOSI goes on MOSI and MISO goes on MISO, they are not swapped.
### For normal operation
The following connections are only needed when the microcontroller is disconnected from the Arduino.
* Place a pull-up resistor on the Reset pin (10kΩ resistor between Reset and VCC).
* Place a 100µF capacitor between GND and VCC.
* The oscillator and ceramic capacitors are still needed.
* VCC and AVCC still have to be connected.
## Program
I'm using the Arduino IDE.
First, we program the Arduino board to make it operating as a relay between the computer and the microcontroller:
1. Open the example sketch `ArduinoISP`.
1. If using an Arduino Uno, uncomment the line `#define USE_OLD_STYLE_WIRING`.
1. Choose your programmer board as board type (_Arduino Micro_ in my case).
1. Choose a regular programmer (typically _AVR ISP_).
1. Upload the sketch normally.
Now we can program the microcontroller:
1. Open the wanted sketch. (or start with the `Blink` example)
1. Choose _Arduino Uno_ as board type. (even if you're using another board as a programmer; it's because a standalone Atmega328P with a 16MHz oscillator behaves like an Arduino Uno)
1. Choose _Arduino as ISP_ as programmer.
1. If your microcontroller doesn't contain a bootloader yet, upload the bootloader using _Tools -> Burn bootloader_.
1. Upload the sketch using _Sketch -> Upload using programmer_.

View File

@ -0,0 +1,15 @@
+++
title = "Homomorfia kriptografio"
date = 2022-03-04
description = "Kurta prezento de la homomorfia kriptografio, kun ekzemploj kaj uzadoj (franca)"
[taxonomies]
tags = ["kriptografio", "matematiko"]
[extra]
katex = true
+++
$$f:(G,*)\longrightarrow (G',\star)\quad|\quad\forall (g,h)\in G^2,~f(g *h)=f(g)\star f(h)$$
Ĉi tiu dokumento estas komprenebla per studentoj en unua yaro de matematiko. Ĝi rapide prezentas homomorfian kriptografion, iom ekzemplojn kaj uzadojn.
[Legi PDF (franca)](//cloud.txmn.tk/index.php/s/EygkDWqCsZLiTaL/download?path=&files=mss.pdf)

View File

@ -0,0 +1,15 @@
+++
title = "Chiffrement homomorphe"
date = 2022-03-04
description = "Une présentation rapide du chiffrement homomorphe, de quelques exemples et de ses applications."
[taxonomies]
tags = ["cryptographie", "mathématiques"]
[extra]
katex = true
+++
$$f:(G,*)\longrightarrow (G',\star)\quad|\quad\forall (g,h)\in G^2,~f(g *h)=f(g)\star f(h)$$
Ce document de niveau troisième semestre de mathématiques (prérequis&nbsp;: bases d'algèbre linéaire et d'arithmétique) présente rapidement le chiffrement homomorphe, quelques exemples et applications.
[Lire au format PDF](//cloud.txmn.tk/index.php/s/EygkDWqCsZLiTaL/download?path=&files=mss.pdf)

View File

@ -0,0 +1,15 @@
+++
title = "Homomorphic encryption"
date = 2022-03-04
description = "A quick overview of homomorphic encryption, examples and applications (French)"
[taxonomies]
tags = ["cryptography", "mathematics"]
[extra]
katex = true
+++
$$f:(G,*)\longrightarrow (G',\star)\quad|\quad\forall (g,h)\in G^2,~f(g *h)=f(g)\star f(h)$$
This document is accessible to a student in first year of mathematics. It briefly introduces homomorphic encryption, some examples and its applications.
[Read PDF (French)](//cloud.txmn.tk/index.php/s/EygkDWqCsZLiTaL/download?path=&files=mss.pdf)

View File

@ -0,0 +1,59 @@
+++
title = "Minitel kiel terminalo GNU/Linux"
date = 2022-05-15
description = "Ankoraŭ provo uzi Minitel kiel terminalo."
draft=true
[taxonomies]
tags = ["Minitel", "retro", "Arduino"]
+++
**Celo: uzi unu [Minitel](https://eo.wikipedia.org/wiki/Minitel) kiel terminalo de sistemo GNU/Linux.**
{{ float_img(alt="Minitel elmontranta la logotipon de Rust.", src="minitel_rust.jpg", style="max-height:100vh;max-width:min(800px,100%)") }}
Ĉi tio artikolo publikiĝis en la franclingva revuo [_Programmez!_ #256](https://www.programmez.com/magazine/programmez-253-pdf), kio enhavas multajn artikolojn pri la Minitel kaj sia interfacaĵo.
## 😎 La erao de la ĉirkaŭ-komputiko {#ĉirkaŭ-komputiko}
La Minitel enhavas ĉirkaŭ-komputikan kontaktilon (france "prise péri-informatique"), kiu estas eneligo. Por komuniki kun ĝi, sufiĉas seria interfaco. Do mi uzis Arduinon kiel ponto inter Minitel kaj komputilo. Zorgu tamen, necesas Arduino kun multaj seriaj interfacoj (ekzemple la Mega). Ĉi tio evitas al ni programi serian pelilon. La normo ĉirkaŭ-komputiko uzas preskaŭ ASCII 7-bitoj en bitokoj. La fortpeza bito estas la kontrolsumo.
## 🔌 Elektroniko {#elektroniko}
{{ float_img(alt="Konektoskemo", src="minitel_wiring.svg", style="width:300px;background-color:#fff") }}
* Konektu la GND de la Minitel (stifto 2, en la medio) al GND de la Arduino;
* Konektu la RX de la Minitel (stifto 1, en la tute maldekstro de GND) al TX1 de la Arduino;
* Konektu la RX1 de la Arduino al TX de la Minitel (stifto 3, en la tute dekstro de GND) tra 220Ω rezistilo, kaj al +5V tra _pull-up_ 2200Ω rezistilo (ĉiu valoro inter 1kΩ kaj 20kΩ devus funkcii). La rezistilo necesas ĉar la eligo de la Minitel estas +8,5V.
## 💻️ Programaro {#programaro}
Unue mi programis kontrolilon en Python. Ĝi simulas terminalon, kun USB kiel eneligo. Ĝi legas komandan linion, kaj ĝin efektivigas kiam la klavo "Sendo" frapiĝas.
{{ float_img(alt="Minitel ekmontranta la logotipon de Rust.", src="minitel_fortune.jpg", style="max-height:100vh;max-width:min(800px,100%)") }}
Tio sola malfaciligis:
* Ne estas klavo "Novan Linion". Nur klavo "Ĉaretrevenigo". Sed feliĉe estas la bitoko "Novan Linion", ni do povas uzi CRLF.
* Il n'y a pas de touche Nouvelle Ligne. Seulement une touche Retour Chariot. Mais par miracle le caractère Nouvelle Ligne existe, on peut donc utiliser du CRLF. Ça veut dire qu'il faut interpréter la touche Envoi (qui a un code sur deux octets) comme LF, et transformer les LF venant de Linux en CRLF.
* Les accents ne sont pas standard. Une lettre accentuée fait trois octets&nbsp;: un qui indique un caractère spécial, un qui spécifie l'accent, et la lettre. Et attention&#8239;! On a droit aux majuscules accentuées (coucou Windows, le Minitel fait une chose mieux que toi), mais seulement les accents franchouillards. La piñata et le glacier [würmien](https://fr.wiktionary.org/wiki/würmien) n'ont pas la nationalité.
* Le clavier est en majuscule, et les minuscules demandent l'appui de Maj. Si on veut inverser ce comportement, on doit pour chaque lettre arrivant au contrôleur, renvoyer un retour arrière puis la lettre en casse inversée. On voit le clignotement à l'écran et ça oblige à taper assez lentement pour que la réécriture ait le temps de s'opérer.
* Le port péri-informatique supporte 1200 bit/s, soit un rafraîchissement complet de l'écran en plus de 6 secondes. Certains modèles sont plus rapides, jusqu'à 9600 bit/s. Cette lenteur oblige à optimiser l'affichage pour plus d'immédiateté. On ne peut pas rafraîchir tout l'écran en permanence, il faut envoyer uniquement les caractères qui changent. Donc s'il y a un bug (un imprévu dans le programme, un problème de signal, un utilisateur qui tape trop vite), l'écran ne sera pas dans l'état attendu, et le programme, qui n'a aucun moyen de le savoir, continuera même s'il écrit n'importe quoi.
* En mode semi-graphique, les caractères sont remplacés par une grille de 2×3 pixels. On peut alors dessiner, en convertissant les images correctement. On a même quelques nuances de gris&#8239;! (pas 50 mais c'est déjà bien) L'inconvénient, c'est que le changement de couleur agit sur le caractère entier, soit 6 pixels, et non sur chaque pixel individuellement. La gestion de la couleur est donc un peu délicate.
* Si l'affichage est modifié en permanence, par exemple dans un jeu de Snake pour déplacer le serpent, l'appui de n'importe quelle touche peut interférer avec un caractère spécial de plusieurs octets envoyé par le contrôleur. Il en résulte un comportement imprévisible, et souvent un caractère aléatoire qui s'affiche. C'est pourquoi dans le Snake et dans le Tetris que j'ai faits, l'écran se retrouve vite constellé de caractères. J'ai essayé de nettoyer des petites parties différentes de l'écran en permanence, par exemple ligne par ligne, mais cela prend trop de temps, réduit la réactivité du jeu et n'est pas très efficace.
* L'écran est très petit, 40×24 caractères seulement. Aussi, il ne défile pas mais reboucle en haut quand le curseur arrive en bas. Il n'est donc pas vraiment adapté à un terminal de type Unix. Il faut soit créer un système de pagination, qui nettoie l'écran à chaque page, soit accepter de reboucler et nettoyer la fin de la ligne.
* Certains caractères manquent, comme la barre verticale `|`. Cette dernière étant indispensable dans un terminal, j'ai décidé de la substituer aux accents circonflexes `^` qui sont bizarrement affichés `↑` sur le Minitel.
* Côté Linux ce n'est pas facile non plus... Il faut pouvoir indiquer aux programmes la taille du terminal, qu'ils comprennent qu'ils sont dans un terminal et non dans un script, pour que par exemple bash écrive son invite de commande (_prompt_), gérer le retour arrière (qui n'est pas géré directement par bash), etc.
Toutes ces contraintes rendent la conception d'un terminal générique compliquée. Il faut que chaque programme adapte sa gestion du clavier et de l'affichage, car les besoins sont différents pour un utilitaire en ligne de commande, un éditeur de texte, une messagerie instantanée ou un jeu en temps réel.
On m'a donc donné l'idée d'une approche différente&nbsp;: plutôt que d'envoyer la sortie des programmes au Minitel, on garde un tampon de l'écran du Minitel en mémoire. C'est un tableau de l'état de chaque caractère, dont le mode texte ou semi-graphique, la couleur, le clignotement, le code du caractère, etc. Les programmes écrivent dedans, puis demandent au contrôleur de l'envoyer. Au prix de calculs plus lents (ce qui reste négligeable), l'algorithme cherche alors à envoyer le moins de données possibles. Les caractères inchangés ne sont pas renvoyés, on profite de l'instruction plaçant le curseur à la position donnée et de celle permettant de répéter les N derniers caractères.
J'ai implémenté ce nouveau contrôleur en [Rust](https://www.rust-lang.org/) (un langage bas-niveau offrant des abstractions haut-niveau sans coût et la sécurité de la mémoire), ce qui permet un code plus propre, sûr et rapide qu'en Python. C'est une bibliothèque réutilisable (publiée sous licence libre GNU AGPL), que j'ai pu utiliser pour faire un terminal, un Tetris et un Snake.
Au prix de [quelques nanosieverts](https://en.wikipedia.org/w/index.php?title=Cathode-ray_tube&oldid=1087446467#Ionizing_radiation) et d'un ultrason désagréable, cette petite aventure rétro m'a plongé dans une époque que je n'ai pas connue, [quoique j'y vis peut-être encore](https://framatube.org/w/9a8642c0-62f0-4060-95e4-088de9c5db00).
Ressources utiles&nbsp;:
* [Dépôt Git du code du projet](https://git.jeunes-science.asso.fr/tuxmain/Minitel)
* [Notice du Minitel 1 Bistandard (PDF)](https://wiki.labomedia.org/images/c/c7/Minitel1BAlcatel1.pdf)
* [Table des codes de programmation du Minitel](http://millevaches.hydraule.org/info/minitel/specs/codes.htm)
* [Jeunes-Science Bordeaux](https://www.jeunes-science.asso.fr/), club de loisirs scientifiques, disposant entre autres de pièces de collection telles que le Minitel qui a été utilisé pour réaliser ce projet.

View File

@ -0,0 +1,57 @@
+++
title = "Le Minitel comme terminal GNU/Linux"
date = 2022-07-02
description = "Encore une tentative d'utilisation d'un Minitel comme terminal."
[taxonomies]
tags = ["Minitel", "rétro", "Arduino"]
+++
**Objectif&nbsp;: utiliser un [Minitel](https://fr.wikipedia.org/wiki/Minitel) comme terminal d'un système GNU/Linux.**
{{ float_img(alt="Minitel affichant le logo de Rust.", src="minitel_rust.jpg", style="max-height:100vh;max-width:min(800px,100%)") }}
Cet article est paru dans le magazine [_Programmez!_ #256](https://www.programmez.com/magazine/programmez-253-pdf), qui contient plusieurs autres articles concernant le Minitel et son interfaçage.
## 😎 L'ère de la péri-informatique {#péri-informatique}
Le Minitel dispose d'une prise "péri-informatique", qui est un port série d'entrée-sortie. Il suffit pour communiquer avec d'une interface série. J'ai donc utilisé une Arduino comme pont entre le Minitel et l'ordinateur. Mais attention, il faut un Arduino possédant plusieurs interfaces série (comme le Mega). Cela nous évite d'avoir à coder un pilote série logiciel. Le standard péri-informatique utilise à peu près de l'ASCII 7 bits et un découpage en octets. Le bit de poids fort est la somme de contrôle des 7 autres.
## 🔌 Électronique {#électronique}
{{ float_img(alt="Schéma du branchement", src="minitel_wiring.svg", style="width:300px;background-color:#fff") }}
* Connectez le GND du Minitel (pin 2, celui du milieu) au GND de l'Arduino&#8239;;
* Connectez le RX du Minitel (pin 1, tout à gauche du GND) au TX1 de l'Arduino&#8239;;
* Connectez le RX1 de l'Arduino au TX du Minitel (pin 3, tout à droite du GND) à travers une résistance de 220Ω, et au +5V à travers une résistance pull-up de 2200Ω (toute valeur entre 1kΩ et 20kΩ devrait marcher). La résistance est nécessaire car la sortie du Minitel est en +8,5V.
## 💻️ Logiciel {#logiciel}
J'ai d'abord codé un contrôleur en Python. C'est une sorte d'émulateur de terminal, avec le port USB comme entrée-sortie. Il prend une ligne de commande et l'exécute à l'appui de la touche Envoi.
{{ float_img(alt="Minitel affichant le logo de Rust.", src="minitel_fortune.jpg", style="max-height:100vh;max-width:min(800px,100%)") }}
Rien que ça demandait de surmonter plusieurs difficultés&nbsp;:
* Il n'y a pas de touche Nouvelle Ligne. Seulement une touche Retour Chariot. Mais par miracle le caractère Nouvelle Ligne existe, on peut donc utiliser du CRLF. Ça veut dire qu'il faut interpréter la touche Envoi (qui a un code sur deux octets) comme LF, et transformer les LF venant de Linux en CRLF.
* Les accents ne sont pas standard. Une lettre accentuée fait trois octets&nbsp;: un qui indique un caractère spécial, un qui spécifie l'accent, et la lettre. Et attention&#8239;! On a droit aux majuscules accentuées (coucou Windows, le Minitel te surpasse), mais seulement les accents franchouillards. La piñata et le glacier [würmien](https://fr.wiktionary.org/wiki/würmien) n'ont pas la nationalité.
* Le clavier est en majuscule, et les minuscules demandent l'appui de Maj. Si on veut inverser ce comportement, on doit pour chaque lettre arrivant au contrôleur, renvoyer un retour arrière puis la lettre en casse inversée. On voit le clignotement à l'écran et ça oblige à taper assez lentement pour que la réécriture ait le temps de s'opérer.
* Le port péri-informatique supporte 1200 bit/s, soit un rafraîchissement complet de l'écran en plus de 6 secondes. Certains modèles sont plus rapides, jusqu'à 9600 bit/s. Cette lenteur oblige à optimiser l'affichage pour plus d'immédiateté. On ne peut pas rafraîchir tout l'écran en permanence, il faut envoyer uniquement les caractères qui changent. Donc s'il y a un bug (un imprévu dans le programme, un problème de signal, un utilisateur qui tape trop vite), l'écran ne sera pas dans l'état attendu, et le programme, qui n'a aucun moyen de le savoir, continuera même s'il écrit n'importe quoi.
* En mode semi-graphique, les caractères sont remplacés par une grille de 2×3 pixels. On peut alors dessiner, en convertissant les images correctement. On a même quelques nuances de gris&#8239;! (pas 50 mais c'est déjà bien) L'inconvénient, c'est que le changement de couleur agit sur le caractère entier, soit 6 pixels, et non sur chaque pixel individuellement. La gestion de la couleur est donc un peu délicate.
* Si l'affichage est modifié en permanence, par exemple dans un jeu de Snake pour déplacer le serpent, l'appui de n'importe quelle touche peut interférer avec un caractère spécial de plusieurs octets envoyé par le contrôleur. Il en résulte un comportement imprévisible, et souvent un caractère aléatoire qui s'affiche. C'est pourquoi dans le Snake et dans le Tetris que j'ai faits, l'écran se retrouve vite constellé de caractères. J'ai essayé de nettoyer des petites parties différentes de l'écran en permanence, par exemple ligne par ligne, mais cela prend trop de temps, réduit la réactivité du jeu et n'est pas très efficace.
* L'écran est très petit, 40×24 caractères seulement. Aussi, il ne défile pas mais reboucle en haut quand le curseur arrive en bas. Il n'est donc pas vraiment adapté à un terminal de type Unix. Il faut soit créer un système de pagination, qui nettoie l'écran à chaque page, soit accepter de reboucler et nettoyer la fin de la ligne.
* Certains caractères manquent, comme la barre verticale `|`. Cette dernière étant indispensable dans un terminal, j'ai décidé de la substituer aux accents circonflexes `^` qui sont bizarrement affichés `↑` sur le Minitel.
* Côté Linux ce n'est pas facile non plus... Il faut pouvoir indiquer aux programmes la taille du terminal, qu'ils comprennent qu'ils sont dans un terminal et non dans un script, pour que par exemple bash écrive son invite de commande (_prompt_), gérer le retour arrière (qui n'est pas géré directement par bash), etc.
Toutes ces contraintes rendent la conception d'un terminal générique compliquée. Il faut que chaque programme adapte sa gestion du clavier et de l'affichage, car les besoins sont différents pour un utilitaire en ligne de commande, un éditeur de texte, une messagerie instantanée ou un jeu en temps réel.
On m'a donc donné l'idée d'une approche différente&nbsp;: plutôt que d'envoyer la sortie des programmes au Minitel, on garde un tampon de l'écran du Minitel en mémoire. C'est un tableau de l'état de chaque caractère, dont le mode texte ou semi-graphique, la couleur, le clignotement, le code du caractère, etc. Les programmes écrivent dedans, puis demandent au contrôleur de l'envoyer. Au prix de calculs plus lents (ce qui reste négligeable), l'algorithme cherche alors à envoyer le moins de données possibles. Les caractères inchangés ne sont pas renvoyés, on profite de l'instruction plaçant le curseur à la position donnée et de celle permettant de répéter les N derniers caractères.
J'ai implémenté ce nouveau contrôleur en [Rust](https://www.rust-lang.org/) (un langage bas-niveau offrant des abstractions haut-niveau sans coût et la sécurité de la mémoire), ce qui permet un code plus propre, sûr et rapide qu'en Python. C'est une bibliothèque réutilisable (publiée sous licence libre GNU AGPL), que j'ai pu utiliser pour faire un terminal, un Tetris et un Snake.
Au prix de [quelques nanosieverts](https://en.wikipedia.org/w/index.php?title=Cathode-ray_tube&oldid=1087446467#Ionizing_radiation) et d'un ultrason désagréable, cette petite aventure rétro m'a plongé dans une époque que je n'ai pas connue, [quoique j'y vis peut-être encore](https://framatube.org/w/9a8642c0-62f0-4060-95e4-088de9c5db00).
Ressources utiles&nbsp;:
* [Dépôt Git du code du projet](https://git.jeunes-science.asso.fr/tuxmain/Minitel)
* [Notice du Minitel 1 Bistandard (PDF)](https://wiki.labomedia.org/images/c/c7/Minitel1BAlcatel1.pdf)
* [Table des codes de programmation du Minitel](http://millevaches.hydraule.org/info/minitel/specs/codes.htm)
* [Jeunes-Science Bordeaux](https://www.jeunes-science.asso.fr/), club de loisirs scientifiques, disposant entre autres de pièces de collection telles que le Minitel qui a été utilisé pour réaliser ce projet.

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.1 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.3 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.4 MiB

View File

@ -0,0 +1,749 @@
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
version="1.1"
width="4.000500cm" height="4.000500cm" viewBox="0 0 15750 15750">
<title>SVG Picture created as minitel_wiring.svg date 2022/05/09 20:38:52 </title>
<desc>Picture generated by Eeschema-SVG </desc>
<g style="fill:#000000; fill-opacity:1.000000;stroke:#000000; stroke-opacity:1.000000;
stroke-linecap:round; stroke-linejoin:round;"
transform="translate(0 0) scale(1 1)">
</g>
<g style="fill:#000000; fill-opacity:0.0;
stroke:#000000; stroke-width:60.000000; stroke-opacity:1;
stroke-linecap:round; stroke-linejoin:round;">
<g >
</g>
<g style="fill:#840000; fill-opacity:0.0;
stroke:#840000; stroke-width:60.000000; stroke-opacity:1;
stroke-linecap:round; stroke-linejoin:round;">
</g>
<g style="fill:#840000; fill-opacity:0.0;
stroke:#840000; stroke-width:100.000000; stroke-opacity:1;
stroke-linecap:round; stroke-linejoin:round;">
<path d="M4000.012296 10499.962942 A2018.228346 2018.228346 0.0 0 0 5699.029252 12499.834408" />
</g>
<g style="fill:#840000; fill-opacity:0.0;
stroke:#840000; stroke-width:60.000000; stroke-opacity:1;
stroke-linecap:round; stroke-linejoin:round;">
<circle cx="4800.000000" cy="10500.000000" r="200.000000" />
<circle cx="5100.000000" cy="9600.000000" r="200.000000" />
<path style="fill:#840000; fill-opacity:0.0;
stroke:#840000; stroke-width:60.000000; stroke-opacity:1;
stroke-linecap:round; stroke-linejoin:round;fill:none"
d="M 4000.000000,10500.000000
4600.000000,10500.000000
" />
<path style="fill:#840000; fill-opacity:0.0;
stroke:#840000; stroke-width:60.000000; stroke-opacity:1;
stroke-linecap:round; stroke-linejoin:round;fill:none"
d="M 6000.000000,8500.000000
6000.000000,9000.000000
" />
<path style="fill:#840000; fill-opacity:0.0;
stroke:#840000; stroke-width:60.000000; stroke-opacity:1;
stroke-linecap:round; stroke-linejoin:round;fill:none"
d="M 8000.000000,10500.000000
7400.000000,10500.000000
" />
<path style="fill:#840000; fill-opacity:0.0;
stroke:#840000; stroke-width:60.000000; stroke-opacity:1;
stroke-linecap:round; stroke-linejoin:round;fill:none"
d="M 4000.000000,9500.000000
4300.000000,9500.000000
4900.000000,9600.000000
" />
<path style="fill:#840000; fill-opacity:0.0;
stroke:#840000; stroke-width:60.000000; stroke-opacity:1;
stroke-linecap:round; stroke-linejoin:round;fill:none"
d="M 8000.000000,9500.000000
7700.000000,9500.000000
7100.000000,9600.000000
" />
</g>
<g style="fill:#840000; fill-opacity:0.0;
stroke:#840000; stroke-width:100.000000; stroke-opacity:1;
stroke-linecap:round; stroke-linejoin:round;">
<path style="fill:#840000; fill-opacity:0.0;
stroke:#840000; stroke-width:100.000000; stroke-opacity:1;
stroke-linecap:round; stroke-linejoin:round;fill:none"
d="M 5700.000000,12450.000000
5700.000000,12150.000000
6300.000000,12150.000000
6300.000000,12450.000000
" />
</g>
<g style="fill:#840000; fill-opacity:0.0;
stroke:#840000; stroke-width:60.000000; stroke-opacity:1;
stroke-linecap:round; stroke-linejoin:round;">
<circle cx="6000.000000" cy="9200.000000" r="200.000000" />
</g>
<g style="fill:#840000; fill-opacity:0.0;
stroke:#840000; stroke-width:100.000000; stroke-opacity:1;
stroke-linecap:round; stroke-linejoin:round;">
<path d="M6301.115055 12499.813369 A2005.826772 2005.826772 0.0 0 0 8000.002364 10500.094507" />
</g>
<g style="fill:#840000; fill-opacity:0.0;
stroke:#840000; stroke-width:60.000000; stroke-opacity:1;
stroke-linecap:round; stroke-linejoin:round;">
<circle cx="6900.000000" cy="9600.000000" r="200.000000" />
<circle cx="7200.000000" cy="10500.000000" r="200.000000" />
</g>
<g style="fill:#840000; fill-opacity:0.0;
stroke:#840000; stroke-width:100.000000; stroke-opacity:1;
stroke-linecap:round; stroke-linejoin:round;">
<path d="M7999.996954 10496.509343 A2000.000000 2000.000000 0.0 0 0 4000.003046 10496.509343" />
</g>
<g style="fill:#840000; fill-opacity:0.0;
stroke:#840000; stroke-width:60.000000; stroke-opacity:1;
stroke-linecap:round; stroke-linejoin:round;">
<path d="M4000 10500
L3000 10500
" />
<text x="3500.000000" y="10400.000000"
textLength="606.181102" font-size="666.653543" lengthAdjust="spacingAndGlyphs"
text-anchor="middle" opacity="0">1</text>
<g class="stroked-text"><desc>1</desc>
<path d="M3642 10376
L3357 10376
" />
<path d="M3500 10376
L3500 9876
L3452 9947
L3404 9995
L3357 10019
" />
</g><path d="M6000 8500
L6000 7500
" />
<g transform="rotate(-90.000000 5900.000000 8000.000000)">
<text x="5900.000000" y="8000.000000"
textLength="536.181102" font-size="666.653543" lengthAdjust="spacingAndGlyphs"
text-anchor="middle" opacity="0">2</text>
</g>
<g class="stroked-text"><desc>2</desc>
<path d="M5423 8142
L5400 8119
L5376 8071
L5376 7952
L5400 7904
L5423 7880
L5471 7857
L5519 7857
L5590 7880
L5876 8166
L5876 7857
" />
</g><path d="M8000 10500
L9000 10500
" />
<text x="8500.000000" y="10400.000000"
textLength="536.181102" font-size="666.653543" lengthAdjust="spacingAndGlyphs"
text-anchor="middle" opacity="0">3</text>
<g class="stroked-text"><desc>3</desc>
<path d="M8333 9876
L8642 9876
L8476 10066
L8547 10066
L8595 10090
L8619 10114
L8642 10161
L8642 10280
L8619 10328
L8595 10352
L8547 10376
L8404 10376
L8357 10352
L8333 10328
" />
</g><path d="M4000 9500
L3000 9500
" />
<text x="3500.000000" y="9400.000000"
textLength="536.181102" font-size="666.653543" lengthAdjust="spacingAndGlyphs"
text-anchor="middle" opacity="0">4</text>
<g class="stroked-text"><desc>4</desc>
<path d="M3595 9042
L3595 9376
" />
<path d="M3476 8852
L3357 9209
L3666 9209
" />
</g><path d="M8000 9500
L9000 9500
" />
<text x="8500.000000" y="9400.000000"
textLength="536.181102" font-size="666.653543" lengthAdjust="spacingAndGlyphs"
text-anchor="middle" opacity="0">5</text>
<g class="stroked-text"><desc>5</desc>
<path d="M8619 8876
L8380 8876
L8357 9114
L8380 9090
L8428 9066
L8547 9066
L8595 9090
L8619 9114
L8642 9161
L8642 9280
L8619 9328
L8595 9352
L8547 9376
L8428 9376
L8380 9352
L8357 9328
" />
</g></g>
<g style="fill:#008484; fill-opacity:0.0;
stroke:#008484; stroke-width:60.000000; stroke-opacity:1;
stroke-linecap:round; stroke-linejoin:round;">
<text x="6000.039370" y="13749.960630"
textLength="2536.181102" font-size="666.653543" lengthAdjust="spacingAndGlyphs"
text-anchor="middle" opacity="0">Minitel</text>
<g class="stroked-text"><desc>Minitel</desc>
<path d="M4880 13726
L4880 13226
L5047 13583
L5214 13226
L5214 13726
" />
<path d="M5452 13726
L5452 13392
" />
<path d="M5452 13226
L5428 13249
L5452 13273
L5476 13249
L5452 13226
L5452 13273
" />
<path d="M5690 13392
L5690 13726
" />
<path d="M5690 13440
L5714 13416
L5761 13392
L5833 13392
L5880 13416
L5904 13464
L5904 13726
" />
<path d="M6142 13726
L6142 13392
" />
<path d="M6142 13226
L6119 13249
L6142 13273
L6166 13249
L6142 13226
L6142 13273
" />
<path d="M6309 13392
L6500 13392
" />
<path d="M6380 13226
L6380 13654
L6404 13702
L6452 13726
L6500 13726
" />
<path d="M6857 13702
L6809 13726
L6714 13726
L6666 13702
L6642 13654
L6642 13464
L6666 13416
L6714 13392
L6809 13392
L6857 13416
L6880 13464
L6880 13511
L6642 13559
" />
<path d="M7166 13726
L7119 13702
L7095 13654
L7095 13226
" />
</g></g>
</g>
<g style="fill:#008484; fill-opacity:0.0;
stroke:#008484; stroke-width:60.000000; stroke-opacity:1;
stroke-linecap:round; stroke-linejoin:round;">
<g >
</g>
<g style="fill:#840000; fill-opacity:0.0;
stroke:#840000; stroke-width:60.000000; stroke-opacity:1;
stroke-linecap:round; stroke-linejoin:round;">
<path style="fill:#840000; fill-opacity:0.0;
stroke:#840000; stroke-width:60.000000; stroke-opacity:1;
stroke-linecap:round; stroke-linejoin:round;fill:none"
d="M 9700.000000,4000.000000
10000.000000,3500.000000
" />
<path style="fill:#840000; fill-opacity:0.0;
stroke:#840000; stroke-width:60.000000; stroke-opacity:1;
stroke-linecap:round; stroke-linejoin:round;fill:none"
d="M 10000.000000,4500.000000
10000.000000,3500.000000
" />
<path style="fill:#840000; fill-opacity:0.0;
stroke:#840000; stroke-width:60.000000; stroke-opacity:1;
stroke-linecap:round; stroke-linejoin:round;fill:none"
d="M 10000.000000,3500.000000
10300.000000,4000.000000
" />
</g>
<g style="fill:#008484; fill-opacity:0.0;
stroke:#008484; stroke-width:60.000000; stroke-opacity:1;
stroke-linecap:round; stroke-linejoin:round;">
<text x="10000.000000" y="2749.960630"
textLength="1583.818898" font-size="666.653543" lengthAdjust="spacingAndGlyphs"
text-anchor="middle" opacity="0">+5V</text>
<g class="stroked-text"><desc>+5V</desc>
<path d="M9357 2535
L9738 2535
" />
<path d="M9547 2726
L9547 2345
" />
<path d="M10214 2226
L9976 2226
L9952 2464
L9976 2440
L10023 2416
L10142 2416
L10190 2440
L10214 2464
L10238 2511
L10238 2630
L10214 2678
L10190 2702
L10142 2726
L10023 2726
L9976 2702
L9952 2678
" />
<path d="M10380 2226
L10547 2726
L10714 2226
" />
</g></g>
</g>
<g style="fill:#008484; fill-opacity:0.0;
stroke:#008484; stroke-width:60.000000; stroke-opacity:1;
stroke-linecap:round; stroke-linejoin:round;">
<g >
</g>
<g style="fill:#840000; fill-opacity:0.0;
stroke:#840000; stroke-width:60.000000; stroke-opacity:1;
stroke-linecap:round; stroke-linejoin:round;">
</g>
<g style="fill:#840000; fill-opacity:0.0;
stroke:#840000; stroke-width:100.000000; stroke-opacity:1;
stroke-linecap:round; stroke-linejoin:round;">
<rect x="9600.000000" y="5000.000000" width="800.000000" height="2000.000000" rx="0.000000" />
</g>
<g style="fill:#840000; fill-opacity:0.0;
stroke:#840000; stroke-width:60.000000; stroke-opacity:1;
stroke-linecap:round; stroke-linejoin:round;">
<path d="M10000 5000
L10000 4500
" />
<path d="M10000 7000
L10000 7500
" />
</g>
<g style="fill:#008484; fill-opacity:0.0;
stroke:#008484; stroke-width:60.000000; stroke-opacity:1;
stroke-linecap:round; stroke-linejoin:round;">
<text x="11519.330709" y="5749.921260"
textLength="1036.181102" font-size="666.653543" lengthAdjust="spacingAndGlyphs"
text-anchor="middle" opacity="0">R2</text>
<g class="stroked-text"><desc>R2</desc>
<path d="M11435 5726
L11269 5487
" />
<path d="M11150 5726
L11150 5226
L11340 5226
L11388 5249
L11412 5273
L11435 5321
L11435 5392
L11412 5440
L11388 5464
L11340 5487
L11150 5487
" />
<path d="M11626 5273
L11650 5249
L11697 5226
L11816 5226
L11864 5249
L11888 5273
L11912 5321
L11912 5368
L11888 5440
L11602 5726
L11912 5726
" />
</g><text x="11983.622047" y="6749.921260"
textLength="1964.763780" font-size="666.653543" lengthAdjust="spacingAndGlyphs"
text-anchor="middle" opacity="0">2200</text>
<g class="stroked-text"><desc>2200</desc>
<path d="M11126 6273
L11150 6249
L11197 6226
L11316 6226
L11364 6249
L11388 6273
L11412 6321
L11412 6368
L11388 6440
L11102 6726
L11412 6726
" />
<path d="M11602 6273
L11626 6249
L11674 6226
L11793 6226
L11840 6249
L11864 6273
L11888 6321
L11888 6368
L11864 6440
L11578 6726
L11888 6726
" />
<path d="M12197 6226
L12245 6226
L12293 6249
L12316 6273
L12340 6321
L12364 6416
L12364 6535
L12340 6630
L12316 6678
L12293 6702
L12245 6726
L12197 6726
L12150 6702
L12126 6678
L12102 6630
L12078 6535
L12078 6416
L12102 6321
L12126 6273
L12150 6249
L12197 6226
" />
<path d="M12674 6226
L12721 6226
L12769 6249
L12793 6273
L12816 6321
L12840 6416
L12840 6535
L12816 6630
L12793 6678
L12769 6702
L12721 6726
L12674 6726
L12626 6702
L12602 6678
L12578 6630
L12555 6535
L12555 6416
L12578 6321
L12602 6273
L12626 6249
L12674 6226
" />
</g></g>
</g>
<g style="fill:#008484; fill-opacity:0.0;
stroke:#008484; stroke-width:60.000000; stroke-opacity:1;
stroke-linecap:round; stroke-linejoin:round;">
<g >
</g>
<g style="fill:#840000; fill-opacity:0.0;
stroke:#840000; stroke-width:60.000000; stroke-opacity:1;
stroke-linecap:round; stroke-linejoin:round;">
<path style="fill:#840000; fill-opacity:0.0;
stroke:#840000; stroke-width:60.000000; stroke-opacity:1;
stroke-linecap:round; stroke-linejoin:round;fill:none"
d="M 7500.000000,4500.000000
7500.000000,5000.000000
8000.000000,5000.000000
7500.000000,5500.000000
7000.000000,5000.000000
7500.000000,5000.000000
" />
</g>
<g style="fill:#008484; fill-opacity:0.0;
stroke:#008484; stroke-width:60.000000; stroke-opacity:1;
stroke-linecap:round; stroke-linejoin:round;">
<text x="7500.000000" y="6749.960630"
textLength="1583.818898" font-size="666.653543" lengthAdjust="spacingAndGlyphs"
text-anchor="middle" opacity="0">GND</text>
<g class="stroked-text"><desc>GND</desc>
<path d="M7119 6249
L7071 6226
L7000 6226
L6928 6249
L6880 6297
L6857 6345
L6833 6440
L6833 6511
L6857 6607
L6880 6654
L6928 6702
L7000 6726
L7047 6726
L7119 6702
L7142 6678
L7142 6511
L7047 6511
" />
<path d="M7357 6726
L7357 6226
L7642 6726
L7642 6226
" />
<path d="M7880 6726
L7880 6226
L8000 6226
L8071 6249
L8119 6297
L8142 6345
L8166 6440
L8166 6511
L8142 6607
L8119 6654
L8071 6702
L8000 6726
L7880 6726
" />
</g></g>
</g>
<g style="fill:#008484; fill-opacity:0.0;
stroke:#008484; stroke-width:60.000000; stroke-opacity:1;
stroke-linecap:round; stroke-linejoin:round;">
<g >
</g>
<g style="fill:#840000; fill-opacity:0.0;
stroke:#840000; stroke-width:60.000000; stroke-opacity:1;
stroke-linecap:round; stroke-linejoin:round;">
</g>
<g style="fill:#840000; fill-opacity:0.0;
stroke:#840000; stroke-width:100.000000; stroke-opacity:1;
stroke-linecap:round; stroke-linejoin:round;">
<rect x="9600.000000" y="8000.000000" width="800.000000" height="2000.000000" rx="0.000000" />
</g>
<g style="fill:#840000; fill-opacity:0.0;
stroke:#840000; stroke-width:60.000000; stroke-opacity:1;
stroke-linecap:round; stroke-linejoin:round;">
<path d="M10000 8000
L10000 7500
" />
<path d="M10000 10000
L10000 10500
" />
</g>
<g style="fill:#008484; fill-opacity:0.0;
stroke:#008484; stroke-width:60.000000; stroke-opacity:1;
stroke-linecap:round; stroke-linejoin:round;">
<text x="11519.330709" y="8749.921260"
textLength="1036.181102" font-size="666.653543" lengthAdjust="spacingAndGlyphs"
text-anchor="middle" opacity="0">R1</text>
<g class="stroked-text"><desc>R1</desc>
<path d="M11435 8726
L11269 8487
" />
<path d="M11150 8726
L11150 8226
L11340 8226
L11388 8249
L11412 8273
L11435 8321
L11435 8392
L11412 8440
L11388 8464
L11340 8487
L11150 8487
" />
<path d="M11912 8726
L11626 8726
" />
<path d="M11769 8726
L11769 8226
L11721 8297
L11674 8345
L11626 8368
" />
</g><text x="11745.551181" y="9749.921260"
textLength="1488.582677" font-size="666.653543" lengthAdjust="spacingAndGlyphs"
text-anchor="middle" opacity="0">220</text>
<g class="stroked-text"><desc>220</desc>
<path d="M11126 9273
L11150 9249
L11197 9226
L11316 9226
L11364 9249
L11388 9273
L11412 9321
L11412 9368
L11388 9440
L11102 9726
L11412 9726
" />
<path d="M11602 9273
L11626 9249
L11674 9226
L11793 9226
L11840 9249
L11864 9273
L11888 9321
L11888 9368
L11864 9440
L11578 9726
L11888 9726
" />
<path d="M12197 9226
L12245 9226
L12293 9249
L12316 9273
L12340 9321
L12364 9416
L12364 9535
L12340 9630
L12316 9678
L12293 9702
L12245 9726
L12197 9726
L12150 9702
L12126 9678
L12102 9630
L12078 9535
L12078 9416
L12102 9321
L12126 9273
L12150 9249
L12197 9226
" />
</g></g>
</g>
<g style="fill:#008484; fill-opacity:0.0;
stroke:#008484; stroke-width:62.519685; stroke-opacity:1;
stroke-linecap:round; stroke-linejoin:round;">
</g>
<g style="fill:#008484; fill-opacity:0.0;
stroke:#008484; stroke-width:60.000000; stroke-opacity:1;
stroke-linecap:round; stroke-linejoin:round;">
</g>
<g style="fill:#000000; fill-opacity:0.0;
stroke:#000000; stroke-width:60.000000; stroke-opacity:1;
stroke-linecap:round; stroke-linejoin:round;">
<text x="2000.000000" y="6862.480315"
textLength="1393.346457" font-size="666.653543" lengthAdjust="spacingAndGlyphs"
text-anchor="start" opacity="0">TX1</text>
<g class="stroked-text"><desc>TX1</desc>
<path d="M2077 6338
L2363 6338
" />
<path d="M2220 6838
L2220 6338
" />
<path d="M2482 6338
L2815 6838
" />
<path d="M2815 6338
L2482 6838
" />
<path d="M3268 6838
L2982 6838
" />
<path d="M3125 6838
L3125 6338
L3077 6410
L3030 6457
L2982 6481
" />
</g></g>
<g style="fill:#000000; fill-opacity:0.0;
stroke:#000000; stroke-width:62.519685; stroke-opacity:1;
stroke-linecap:round; stroke-linejoin:round;">
</g>
<g style="fill:#000000; fill-opacity:0.0;
stroke:#000000; stroke-width:60.000000; stroke-opacity:1;
stroke-linecap:round; stroke-linejoin:round;">
<text x="13500.000000" y="7362.480315"
textLength="1512.362205" font-size="666.653543" lengthAdjust="spacingAndGlyphs"
text-anchor="start" opacity="0">RX1</text>
<g class="stroked-text"><desc>RX1</desc>
<path d="M13934 7338
L13768 7100
" />
<path d="M13649 7338
L13649 6838
L13839 6838
L13887 6862
L13910 6886
L13934 6933
L13934 7005
L13910 7052
L13887 7076
L13839 7100
L13649 7100
" />
<path d="M14101 6838
L14434 7338
" />
<path d="M14434 6838
L14101 7338
" />
<path d="M14887 7338
L14601 7338
" />
<path d="M14744 7338
L14744 6838
L14696 6910
L14649 6957
L14601 6981
" />
</g></g>
<g style="fill:#008400; fill-opacity:0.0;
stroke:#008400; stroke-width:60.000000; stroke-opacity:1;
stroke-linecap:round; stroke-linejoin:round;">
<path d="M6000 7500
L6000 4500
" />
<path d="M9000 10500
L10000 10500
" />
<path d="M2000 10500
L2000 7000
" />
<path d="M6000 4500
L7500 4500
" />
<path d="M3000 10500
L2000 10500
" />
<path d="M10000 7500
L13500 7500
" />
</g>
<g style="fill:#008400; fill-opacity:1.0;
stroke:#008400; stroke-width:60.000000; stroke-opacity:1;
stroke-linecap:round; stroke-linejoin:round;">
<circle cx="10000.000000" cy="7500.000000" r="180.000000" />
</g>
</svg>

After

Width:  |  Height:  |  Size: 17 KiB

25
content/eula.eo.md Normal file
View File

@ -0,0 +1,25 @@
+++
title = "Kondiĉoj de uzo"
+++
Uzante tian servilon, vi devas akcepti la sekvontajn kondiĉojn de uzo.
## Garantioj {#garantioj}
Nepre neniu garantio estas donita pri havebleco, bona funkcio, sekureco, integreco de la servoj, krom la garantio de repago proximume proporcia al la tempo de malhavebleco de la servo (nur se vi pagas servojn).
## Privateco {#privateco}
Nenio dirinda ĉi tie, krom ke mi posedas ĉiujn la datumojn kiujn vi donas al mi, kaj ke mi ne povos pruvi ke mi ne friponas kun ĝi. Bonvolu ne doni ĝin al mi se vi ne volas ke mi havus ĝin.
Pri kuketoj, vi povas diri al vian komputilo se ĝi devas memorigi la kuketojn kiujn mi proponas.
Tamen, unu el miaj celoj pri ĉi tiu servilo, estas ebligi al homoj plibonigi sian privatecon en la reto, do mi ne apriore dissendos viajn datumojn, neniel por komerco aŭ reklamo, sen via antaŭa akordo. Ğenerale, viaj datumojn estas konservitaj nur dum necesaj por sia normala uzo, kaj provizore postreste por anonimaj statistikaĵoj kaj bontenado. Mi ne spionas la uzantojn.
La servilo funkcias preskaŭ sole kun liberaj programoj, ĝenerale desegnitaj por respekti la privatecon de la uzantoj.
## Aŭtorrajtoj {#auxtorrajtoj}
[Avataro: xkcd#614, Aŭtorrajto Randall Munroe, CC BY-NC 2.5](https://xkcd.com/614/)
[Fono de NextCloud: Aŭtorrajto 2013 Sergey Pesterev, CC BY-SA 4.0](https://commons.wikimedia.org/wiki/File:Moonlight_in_the_Sahara.jpg)

27
content/eula.fr.md Normal file
View File

@ -0,0 +1,27 @@
+++
title = "Conditions Générales d'Utilisation"
+++
En utilisant les services fournis via ce serveur, vous devez accepter les Conditions Générales d'Utilisation suivantes.
Notez que certains services peuvent posséder des conditions d'utilisations supplémentaires, accessibles depuis lesdits services.
## Garanties {#garanties}
Absolument aucune garantie n'est donnée sur la disponibilité, le bon fonctionnement, la sécurité, l'intégrité des services fournis via ce serveur, à l'exception d'une garantie de remboursement approximativement proportionnel à la durée d'indisponibilité du service. (en gros, il n'y a pas de garantie, sauf si vous payez un service, et dans ce cas vous serez remboursé·e des périodes d'indisponibilité)
## Confidentialité {#confidentialite}
Rien à dire ici, si ce n'est que je possède toutes les informations que vous me donnez, et que je ne pourrai fournir aucune preuve que je n'en fais rien de mal. SVP, ne me les donnez pas si vous ne voulez pas que je les aie. Contactez-moi pour toute demande à ce sujet.
À propos des cookies, c'est entièrement votre choix de dire à votre ordinateur d'enregistrer ou pas ceux que je lui propose. [Voici par exemple comment faire avec Firefox.](https://support.mozilla.org/fr/kb/protection-renforcee-contre-pistage-firefox-ordinateur)
Un de mes objectifs avec ce serveur est toutefois de permettre aux gens d'améliorer leur vie privée sur le Ouèbe, je ne partagerai donc pas a priori de données à caractère personnel, et en aucun cas je ne les partagerai dans un but commercial ou publicitaire sans accord préalable des personnes concernées. En général, elles ne sont stockées que pendant la durée nécessaire à leur utilisation normale, ainsi que résiduellement dans des journaux temporaires servant pour des statistiques (totalement anonymes) et la maintenance. Aucun système de traçage des utilisateurices n'est mis en place.
Le serveur tourne quasi-exclusivement (c'est-à-dire autant que possible) avec des logiciels libres, généralement conçus pour respecter la vie privée des utilisateurices.
## Crédits {#credits}
[Avatar&nbsp;: xkcd#614, Copyright Randall Munroe, CC BY-NC 2.5](https://xkcd.com/614/)
[Image de fond du NextCloud&nbsp;: CopyLeft 2013 Sergey Pesterev, CC BY-SA 4.0](https://commons.wikimedia.org/wiki/File:Moonlight_in_the_Sahara.jpg)

25
content/eula.md Normal file
View File

@ -0,0 +1,25 @@
+++
title = "End-User License Agreement"
+++
By using the services provided by this server, you must accept the following End-User License Agreement.
## Warranty {#warranty}
Absolutely no warranty is given on availibility, good function, security, integrity of the services provided via this server, expected the warranty of refund approximately proportional to the unavailability duration of the service. (in a nutshell, there is no warranty, except if you are paying for a service, and in that only case you will get refund of the unavailability periods)
## Privacy {#privacy}
Nothing to say here. I just own all the data you give to me, and I could never provide any proof that I am not doing anything bad with them. Please, do not give them if you do not want me to know them.
Speaking of cookies, it is entirely your choice to tell your computer to save or not the cookies I propose to it.
One of my goals with this server is, however, to enable people to improve their privacy on the Web, so a priori I will not share your data, and under no circumstances I will share them for trading or advertisement without your prerequisite agreement. In general, they are only stored during the time they are needed for their normal use, as well as residually in temporary logs for statistics (totally anonymous) and maintenance. No user tracking system is set.
The server runs quasi-exclusively on libre softwares, generally designed to respect users' privacy.
## Credits {#credits}
[Avatar: xkcd#614, Copyright Randall Munroe, CC BY-NC 2.5](https://xkcd.com/614/)
[NextCloud background: CopyLeft 2013 Sergey Pesterev, CC BY-SA 4.0](https://commons.wikimedia.org/wiki/File:Moonlight_in_the_Sahara.jpg)

184
sass/css/style.scss Normal file
View File

@ -0,0 +1,184 @@
@font-face {
font-family: Caladea;
src: url("/fonts/Caladea-Regular.ttf");
}
@font-face {
font-family: CMU-Bright;
src: url("/fonts/cmunbmr.ttf");
}
@font-face {
font-family: "Libertinus Sans";
font-weight: normal;
font-style: normal;
src: url("/fonts/LibertinusSans-Regular.otf");
}
@font-face {
font-family: "Libertinus Sans";
font-weight: bold;
font-style: normal;
src: url("/fonts/LibertinusSans-Bold.otf");
}
@font-face {
font-family: "Libertinus Sans";
font-weight: normal;
font-style: italic;
src: url("/fonts/LibertinusSans-Italic.otf");
}
@font-face {
font-family: SourceCodePro;
src: url("/fonts/SourceCodePro-Regular.otf");
}
html, body {
font-family: "Libertinus Sans", "Linux Biolinum", "Liberation Sans", "Helvetica", "Arial";
font-size: 110%;
}
body {
padding: 16px;
}
h1, h2, h3 {
font-family: Caladea;
font-weight: normal;
}
h1 {
font-size: 2.5em;
}
h2 {
font-size: 2em;
}
h3 {
font-size: 1.5em;
}
.service_boxes {
text-align: center;
}
.service_box {
display: inline-block;
width: 144px;
padding-top: 4px;
border: 2px solid transparent;
vertical-align: top;
}
.service_box-img {
max-width: 128px;
max-height: 128px;
}
.service_box-img_wrap {
width: 128px;
height: 128px;
margin: auto;
display: flex;
justify-content: center;
align-items: center;
}
.service_box-link, .service_box-link:visited {
color: #000;
font-family: CMU-Bright;
text-decoration: none;
}
.service_box-title {
position: relative;
top: 14px;
display: inline-block;
padding-bottom: 14px;
}
.service_box:hover, .service_box:focus {
border-top-color: #000;
border-left-color: #000;
border-bottom-color: #f00;
border-right-color: #f00;
}
.article-list_title {
margin-bottom: 0;
}
code, pre {
font-family: SourceCodePro, monospace, monospace;
}
.anchor, .anchor:visited {
margin-left: -1rem;
margin-right: 0.75rem;
color: #aaa;
text-decoration: none;
font-size: 2rem;
font-family: LinBiolinum;
}
.anchor:hover, .anchor:focus {
color: #f00;
}
@media (prefers-color-scheme: dark) {
html {
background-color: #000;
color: #fff;
}
a {
color: #fa4;
}
a:visited {
color: #fc8;
}
.service_box:hover, .service_box:focus {
border-top-color: #fff;
border-left-color: #fff;
}
.service_box-img_wrap {
background-color: #fff;
box-shadow: 0 0 3px 5px #fff;
}
.service_box-link, .service_box-link:visited {
color: #fff;
}
}
.float_img {
float: right;
max-width: 100%;
margin: 4px;
}
footer {
margin-top: 64px;
}
footer hr {
border: 1px dashed #fa4;
}
.mastodon-logo img {
width: 48px;
margin: 24px;
}
.hidden {
opacity: 0;
}
.hidden:hover, .hidden:focus {
opacity: 1;
}

BIN
static/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.6 KiB

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
static/fonts/cmunbmr.ttf Normal file

Binary file not shown.

13
static/humans.txt Normal file
View File

@ -0,0 +1,13 @@
/* TEAM */
Author: tuxmain
Contact: t åt txmn døt tk
Site: https://txmn.tk
Location: Bègles, France
/* THANKS */
h30x: https://git.42l.fr/HugoTrentesaux/toucan
/* SITE */
Language: English, French, Esperanto, Spanish
Components: katex
Software: Zola, VSCodium, Filezilla, Apache

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

BIN
static/img/dubitaristes.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

157
static/img/element.svg Normal file
View File

@ -0,0 +1,157 @@
<svg width="128" height="128" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
<g filter="url(#a)">
<path fill-rule="evenodd" clip-rule="evenodd" d="M16.144 2.344H7.856c-1.917 0-2.612.2-3.312.574a3.91 3.91 0 0 0-1.626 1.626c-.375.7-.574 1.395-.574 3.312v8.288c0 1.917.2 2.612.574 3.312a3.91 3.91 0 0 0 1.626 1.626c.7.375 1.395.574 3.312.574h8.288c1.917 0 2.612-.2 3.312-.574a3.91 3.91 0 0 0 1.626-1.626c.375-.7.574-1.395.574-3.312V7.856c0-1.917-.2-2.612-.574-3.312a3.907 3.907 0 0 0-1.626-1.626c-.7-.375-1.395-.574-3.312-.574Z" fill="url(#b)"/>
</g>
<g filter="url(#c)">
<path fill-rule="evenodd" clip-rule="evenodd" d="M10.097 6.019c0-.45.365-.816.816-.816a5.438 5.438 0 0 1 5.437 5.438.816.816 0 1 1-1.631 0 3.806 3.806 0 0 0-3.806-3.807.816.816 0 0 1-.816-.815Z" fill="#fff"/>
</g>
<g filter="url(#d)">
<path fill-rule="evenodd" clip-rule="evenodd" d="M13.903 17.981c0 .45-.365.816-.816.816a5.438 5.438 0 0 1-5.437-5.438.816.816 0 1 1 1.631 0 3.806 3.806 0 0 0 3.806 3.807c.451 0 .816.365.816.815Z" fill="#fff"/>
</g>
<g filter="url(#e)">
<path fill-rule="evenodd" clip-rule="evenodd" d="M6.019 13.903a.816.816 0 0 1-.816-.816 5.438 5.438 0 0 1 5.438-5.437.816.816 0 1 1 0 1.631 3.806 3.806 0 0 0-3.807 3.806.815.815 0 0 1-.815.816Z" fill="#fff"/>
</g>
<g filter="url(#f)">
<path fill-rule="evenodd" clip-rule="evenodd" d="M17.981 10.097c.45 0 .816.365.816.816a5.438 5.438 0 0 1-5.438 5.437.816.816 0 1 1 0-1.631 3.806 3.806 0 0 0 3.807-3.806c0-.451.365-.816.815-.816Z" fill="#fff"/>
</g>
<defs>
<filter id="a" x="1.547" y="1.922" width="20.906" height="20.906" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
<feOffset dy=".375"/>
<feGaussianBlur stdDeviation=".398"/>
<feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.09 0"/>
<feBlend in2="BackgroundImageFix" result="effect1_dropShadow"/>
<feColorMatrix in="SourceAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
<feOffset dy=".234"/>
<feGaussianBlur stdDeviation=".281"/>
<feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.25 0"/>
<feBlend in2="effect1_dropShadow" result="effect2_dropShadow"/>
<feBlend in="SourceGraphic" in2="effect2_dropShadow" result="shape"/>
</filter>
<filter id="c" x="6.956" y="4.031" width="12.534" height="12.534" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
<feOffset dy=".328"/>
<feGaussianBlur stdDeviation=".516"/>
<feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.15 0"/>
<feBlend in2="BackgroundImageFix" result="effect1_dropShadow"/>
<feColorMatrix in="SourceAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
<feOffset dy="1.266"/>
<feGaussianBlur stdDeviation=".633"/>
<feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.15 0"/>
<feBlend in2="effect1_dropShadow" result="effect2_dropShadow"/>
<feColorMatrix in="SourceAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
<feOffset dy="1.969"/>
<feGaussianBlur stdDeviation="1.57"/>
<feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.1 0"/>
<feBlend mode="overlay" in2="effect2_dropShadow" result="effect3_dropShadow"/>
<feColorMatrix in="SourceAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
<feOffset dx="-.188" dy=".422"/>
<feGaussianBlur stdDeviation=".34"/>
<feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.1 0"/>
<feBlend mode="overlay" in2="effect3_dropShadow" result="effect4_dropShadow"/>
<feBlend in="SourceGraphic" in2="effect4_dropShadow" result="shape"/>
<feColorMatrix in="SourceAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="-.68"/>
<feGaussianBlur stdDeviation=".27"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix values="0 0 0 0 0.678431 0 0 0 0 0.819608 0 0 0 0 0.726431 0 0 0 1 0"/>
<feBlend in2="shape" result="effect5_innerShadow"/>
</filter>
<filter id="d" x="4.509" y="11.372" width="12.534" height="12.534" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
<feOffset dy=".328"/>
<feGaussianBlur stdDeviation=".516"/>
<feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.15 0"/>
<feBlend in2="BackgroundImageFix" result="effect1_dropShadow"/>
<feColorMatrix in="SourceAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
<feOffset dy="1.266"/>
<feGaussianBlur stdDeviation=".633"/>
<feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.15 0"/>
<feBlend in2="effect1_dropShadow" result="effect2_dropShadow"/>
<feColorMatrix in="SourceAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
<feOffset dy="1.969"/>
<feGaussianBlur stdDeviation="1.57"/>
<feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.1 0"/>
<feBlend mode="overlay" in2="effect2_dropShadow" result="effect3_dropShadow"/>
<feColorMatrix in="SourceAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
<feOffset dx="-.188" dy=".422"/>
<feGaussianBlur stdDeviation=".34"/>
<feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.1 0"/>
<feBlend mode="overlay" in2="effect3_dropShadow" result="effect4_dropShadow"/>
<feBlend in="SourceGraphic" in2="effect4_dropShadow" result="shape"/>
<feColorMatrix in="SourceAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="-.68"/>
<feGaussianBlur stdDeviation=".27"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix values="0 0 0 0 0.678431 0 0 0 0 0.819608 0 0 0 0 0.726431 0 0 0 1 0"/>
<feBlend in2="shape" result="effect5_innerShadow"/>
</filter>
<filter id="e" x="2.063" y="6.478" width="12.534" height="12.534" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
<feOffset dy=".328"/>
<feGaussianBlur stdDeviation=".516"/>
<feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.15 0"/>
<feBlend in2="BackgroundImageFix" result="effect1_dropShadow"/>
<feColorMatrix in="SourceAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
<feOffset dy="1.266"/>
<feGaussianBlur stdDeviation=".633"/>
<feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.15 0"/>
<feBlend in2="effect1_dropShadow" result="effect2_dropShadow"/>
<feColorMatrix in="SourceAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
<feOffset dy="1.969"/>
<feGaussianBlur stdDeviation="1.57"/>
<feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.1 0"/>
<feBlend mode="overlay" in2="effect2_dropShadow" result="effect3_dropShadow"/>
<feColorMatrix in="SourceAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
<feOffset dx="-.188" dy=".422"/>
<feGaussianBlur stdDeviation=".34"/>
<feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.1 0"/>
<feBlend mode="overlay" in2="effect3_dropShadow" result="effect4_dropShadow"/>
<feBlend in="SourceGraphic" in2="effect4_dropShadow" result="shape"/>
<feColorMatrix in="SourceAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="-.68"/>
<feGaussianBlur stdDeviation=".27"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix values="0 0 0 0 0.678431 0 0 0 0 0.819608 0 0 0 0 0.726431 0 0 0 1 0"/>
<feBlend in2="shape" result="effect5_innerShadow"/>
</filter>
<filter id="f" x="9.403" y="8.925" width="12.534" height="12.534" filterUnits="userSpaceOnUse" color-interpolation-filters="sRGB">
<feFlood flood-opacity="0" result="BackgroundImageFix"/>
<feColorMatrix in="SourceAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
<feOffset dy=".328"/>
<feGaussianBlur stdDeviation=".516"/>
<feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.15 0"/>
<feBlend in2="BackgroundImageFix" result="effect1_dropShadow"/>
<feColorMatrix in="SourceAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
<feOffset dy="1.266"/>
<feGaussianBlur stdDeviation=".633"/>
<feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.15 0"/>
<feBlend in2="effect1_dropShadow" result="effect2_dropShadow"/>
<feColorMatrix in="SourceAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
<feOffset dy="1.969"/>
<feGaussianBlur stdDeviation="1.57"/>
<feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.1 0"/>
<feBlend mode="overlay" in2="effect2_dropShadow" result="effect3_dropShadow"/>
<feColorMatrix in="SourceAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0"/>
<feOffset dx="-.188" dy=".422"/>
<feGaussianBlur stdDeviation=".34"/>
<feColorMatrix values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.1 0"/>
<feBlend mode="overlay" in2="effect3_dropShadow" result="effect4_dropShadow"/>
<feBlend in="SourceGraphic" in2="effect4_dropShadow" result="shape"/>
<feColorMatrix in="SourceAlpha" values="0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 127 0" result="hardAlpha"/>
<feOffset dy="-.68"/>
<feGaussianBlur stdDeviation=".27"/>
<feComposite in2="hardAlpha" operator="arithmetic" k2="-1" k3="1"/>
<feColorMatrix values="0 0 0 0 0.678431 0 0 0 0 0.819608 0 0 0 0 0.726431 0 0 0 1 0"/>
<feBlend in2="shape" result="effect5_innerShadow"/>
</filter>
<linearGradient id="b" x1="12" y1="2.344" x2="12" y2="21.656" gradientUnits="userSpaceOnUse">
<stop stop-color="#1ED9A3"/>
<stop offset="1" stop-color="#0DBD8B"/>
</linearGradient>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 9.9 KiB

BIN
static/img/etherpad.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 28 KiB

BIN
static/img/forceatlas2.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 38 KiB

BIN
static/img/framadate.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.1 KiB

7
static/img/gbreve.svg Normal file
View File

@ -0,0 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="512" height="512" viewBox="-1 -1 2 2">
<g id="gbreve" transform="scale(0.25)">
<path id="g" d="M 0.7071,0.7071 A 1,1 0 1,1 0.866,-0.5 L 1.7321,-1 A 2,2 0 1,0 1.4142,1.4142 l 0.3536,0.3536 v -1.4142 h -1.4142 z" fill="#000"/>
<path id="breve" d="M 1,0 h 1 A 2,2 0 0,0 -0.5176,-1.9319 L -0.2588,-0.9659 A 1,1 0 0,1 1,0 z" transform="translate(0 -3.14159) scale(0.5) rotate(142.5)" fill="#000"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 497 B

15
static/img/gmixer.svg Normal file
View File

@ -0,0 +1,15 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="100 50 300 400">
<defs>
<radialGradient id="a" gradientUnits="userSpaceOnUse" cx="634" cy="196" r="93" gradientTransform="matrix(.71262 0 0 .7248 685.64 147.836)">
<stop style="stop-color:#fff;stop-opacity:.71" offset="0"/>
<stop style="stop-color:#fff" stop-opacity="0" offset="1"/>
</radialGradient>
<radialGradient xlink:href="#a" id="b" cx="244.29" cy="391.312" fx="244.29" fy="391.312" r="123.851" gradientTransform="matrix(.2252 .69802 -1.12494 .36293 558.094 -50.309)" gradientUnits="userSpaceOnUse"/>
</defs>
<g style="fill:#a10000;fill-opacity:1">
<path class="main" d="m-226.044 501.505 25.83 20.703c-10.935 13.999-27.306 24.055-47.4 26.268a70.052 70.052 0 0 1-64.137-28.173c13.948-10.582 11.248-8.258 26.665-19.577a36.972 36.972 0 0 0 33.85 14.87c10.713-1.181 19.422-6.585 25.192-14.091Z" style="fill:#a10000;fill-opacity:1" transform="translate(466.022 -335.185) scale(.84148)"/>
<path class="G main" d="M-238.615 691.865h93.83v93.83l-24.37-24.37c-23.209 23.798-55.722 39.15-93.554 39.15-46.837 0-90.116-24.986-113.534-65.548-50.46-87.399 12.615-196.647 113.534-196.647 46.359 0 89.232 24.48 112.81 64.312l-54.664 29.284a69.191 69.191 0 0 0-58.146-31.689c-53.263 0-86.552 57.66-59.92 103.786a69.19 69.19 0 0 0 59.92 34.595c20.17 0 37.477-8.268 49.749-21.049Z" style="fill:#a10000;fill-opacity:1" transform="translate(472.022 -315.185) scale(.84148)"/>
</g>
<path style="fill:#666;fill-opacity:1;stroke:none;stroke-width:.93167704;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" d="M200.206 359.964c-.357-1.124-.358-15.064-.003-30.978l.645-28.934 3.43-2.795c8.636-7.036 11.082-11.993 10.085-20.438-.447-3.786-1.247-5.323-4.526-8.695-9.809-10.086-20.16-10.546-31.33-1.393l-4.198 3.44-28.4-2.027c-16.797-1.2-28.815-2.448-29.414-3.057-1.404-1.427-.643-1.919 23.815-15.382 27.595-15.19 26.408-14.72 32.59-12.885 6.305 1.873 13.075 1.33 18.747-1.503 6.534-3.263 8.096-5.39 9.208-12.535 1.224-7.862.807-9.452-3.872-14.767-3.027-3.44-5.215-4.828-10.89-6.91l-7.1-2.606-3.18-6.987c-1.75-3.843-7.165-15.086-12.035-24.983s-8.615-18.617-8.323-19.378c.442-1.152 1.197-1 4.502.91 2.185 1.26 12.566 7.12 23.071 13.022 10.505 5.9 19.872 11.288 20.817 11.973 1.038.752 2.076 3.267 2.624 6.356 1.213 6.843 4.198 11.127 9.924 14.243 8.783 4.781 19.185 3.036 26.262-4.405 3.088-3.247 3.257-3.76 3.174-9.667-.049-3.432-.384-8.126-.745-10.431-.656-4.187-.643-4.213 9.803-19.1a8358.804 8358.804 0 0 0 15.48-22.127c2.76-3.971 5.62-7.22 6.356-7.22 1.131 0 1.336 4.33 1.336 28.213v28.213l-5.233 5.086c-5.956 5.79-6.879 7.645-6.879 13.831 0 9.048 8.536 17.763 18.18 18.563 8.168.677 11.351-.366 16.776-5.497l4.891-4.626 24.564 1.891c31.336 2.413 33.415 2.682 33.415 4.331 0 .727-2.2 2.727-4.89 4.445-6.531 4.17-33.543 19.76-39.244 22.65l-4.538 2.3-6.38-1.564c-14.164-3.471-21.096-.71-26.93 10.724-2.442 4.788-2.348 8.725.35 14.518 2.802 6.019 7.564 9.93 14.731 12.1 4.336 1.313 6.074 2.381 7.414 4.557 3.535 5.74 25.015 48.965 25.015 50.337 0 3.07-4.051 1.423-20.497-8.333-5.38-3.192-14.887-8.608-21.127-12.035l-11.345-6.232-1.39-6.095c-1.774-7.776-5.001-12.62-10.604-15.913-3.74-2.198-5.494-2.614-11.033-2.614-5.626 0-7.15.374-10.467 2.567-4.2 2.776-7.897 8.931-9.41 15.667-.714 3.177-.539 4.816.91 8.492.988 2.505 1.796 4.896 1.796 5.313 0 .88-30.158 46.349-32.357 48.784-1.945 2.154-2.786 2.057-3.57-.414zm45.237-110.328c11.648-4.661 9.954-19.352-2.616-22.69-5.28-1.401-9.65.016-12.805 4.151-3.048 3.997-3.82 8.7-2.002 12.214 3.551 6.867 10.114 9.25 17.423 6.325z"/>
<path d="M192.193 364.74c-.357-1.125-.359-15.065-.003-30.98l.645-28.933 3.43-2.795c8.636-7.037 11.082-11.993 10.085-20.438-.447-3.786-1.248-5.324-4.526-8.695-9.81-10.086-20.16-10.547-31.33-1.393l-4.198 3.44-28.4-2.028c-16.798-1.199-28.815-2.448-29.414-3.057-1.404-1.426-.643-1.918 23.815-15.381 27.595-15.19 26.407-14.721 32.59-12.885 6.305 1.872 13.075 1.33 18.747-1.504 6.533-3.263 8.096-5.39 9.208-12.534 1.224-7.862.807-9.452-3.872-14.768-3.027-3.44-5.216-4.828-10.89-6.91l-7.1-2.605-3.18-6.988c-1.75-3.843-7.165-15.085-12.035-24.982-4.87-9.897-8.615-18.618-8.323-19.378.442-1.152 1.196-1 4.502.91 2.184 1.26 12.566 7.12 23.07 13.021 10.505 5.901 19.873 11.29 20.818 11.974 1.038.752 2.076 3.267 2.624 6.356 1.213 6.843 4.198 11.127 9.923 14.243 8.784 4.78 19.186 3.036 26.263-4.406 3.088-3.246 3.256-3.759 3.173-9.667-.048-3.43-.383-8.125-.744-10.43-.656-4.188-.643-4.213 9.803-19.1a8358.804 8358.804 0 0 0 15.48-22.127c2.76-3.972 5.62-7.221 6.356-7.221 1.13 0 1.336 4.33 1.336 28.213v28.214l-5.233 5.086c-5.956 5.789-6.879 7.644-6.879 13.831 0 9.047 8.536 17.762 18.18 18.562 8.168.678 11.351-.365 16.776-5.496l4.891-4.626 24.564 1.891c31.336 2.413 33.415 2.682 33.415 4.33 0 .728-2.2 2.728-4.891 4.446-6.53 4.17-33.542 19.76-39.243 22.65l-4.538 2.3-6.38-1.564c-14.164-3.471-21.096-.71-26.93 10.723-2.443 4.789-2.348 8.726.35 14.518 2.802 6.02 7.564 9.93 14.73 12.1 4.337 1.314 6.075 2.382 7.415 4.558 3.535 5.74 25.015 48.964 25.015 50.337 0 3.07-4.052 1.423-20.497-8.333-5.38-3.192-14.887-8.608-21.127-12.035l-11.345-6.232-1.39-6.095c-1.774-7.777-5.001-12.62-10.604-15.913-3.74-2.198-5.494-2.614-11.033-2.614-5.626 0-7.151.374-10.468 2.566-4.2 2.777-7.896 8.932-9.41 15.667-.714 3.178-.538 4.816.911 8.492.988 2.505 1.795 4.897 1.795 5.314 0 .88-30.158 46.349-32.357 48.784-1.944 2.154-2.786 2.056-3.57-.414zm45.237-110.33c11.648-4.66 9.954-19.352-2.616-22.689-5.28-1.401-9.65.015-12.805 4.15-3.048 3.997-3.82 8.7-2.002 12.214 3.55 6.868 10.113 9.25 17.423 6.325z" style="fill:url(#b);fill-opacity:1;stroke:none;stroke-width:.93167704;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"/>
</svg>

After

Width:  |  Height:  |  Size: 5.6 KiB

View File

@ -0,0 +1,7 @@
<svg xmlns="http://www.w3.org/2000/svg" width="83" height="30">
<rect fill="#f6c915" x="1" y=".5" width="82" height="29" rx="4"/>
<svg viewBox="0 0 80 80" height="16" width="16" x="7" y="7">
<path d="M25.91 63.04c-3.571 0-6.373-.466-8.41-1.396-2.037-.93-3.495-2.199-4.375-3.809-.88-1.609-1.308-3.457-1.282-5.544.025-2.086.313-4.311.868-6.675l9.579-40.05 11.69-1.81-10.484 43.44a13.563 13.563 0 0 0-.339 2.489c-.026.754.113 1.421.415 1.999.302.579.817 1.044 1.546 1.395.729.353 1.747.579 3.055.679l-2.263 9.278M68.15 38.08c0 3.671-.604 7.03-1.811 10.07-1.207 3.043-2.879 5.669-5.01 7.881-2.138 2.213-4.702 3.935-7.693 5.167-2.992 1.231-6.248 1.848-9.767 1.848-1.71 0-3.42-.151-5.129-.453l-3.394 13.651H24.184l12.52-52.19c2.01-.603 4.311-1.143 6.901-1.622 2.589-.477 5.393-.716 8.41-.716 2.815 0 5.242.428 7.278 1.282 2.037.855 3.708 2.024 5.02 3.507 1.307 1.484 2.274 3.219 2.904 5.205.627 1.987.942 4.11.942 6.373M40.781 53.544c.854.202 1.91.302 3.167.302 1.961 0 3.746-.364 5.355-1.094a11.799 11.799 0 0 0 4.111-3.055c1.131-1.307 2.01-2.877 2.64-4.714.628-1.835.943-3.858.943-6.071 0-2.161-.479-3.998-1.433-5.506-.956-1.508-2.615-2.263-4.978-2.263-1.61 0-3.118.151-4.525.453l-5.28 21.948" fill="#1a171b"/>
</svg>
<text fill="#1a171b" text-anchor="middle" font-family="Helvetica Neue,Helvetica,Arial,sans-serif" font-weight="700" font-size="14" x="50" y="20">Donate</text>
</svg>

After

Width:  |  Height:  |  Size: 1.4 KiB

154
static/img/lstu.svg Normal file
View File

@ -0,0 +1,154 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<svg
xmlns:dc="http://purl.org/dc/elements/1.1/"
xmlns:cc="http://creativecommons.org/ns#"
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
version="1.1"
id="Layer_1"
x="0px"
y="0px"
width="378.51199"
height="378.51199"
viewBox="0 0 378.51201 378.512"
enable-background="new 0 0 304.132 378.512"
xml:space="preserve"
sodipodi:docname="lstu.svg"
inkscape:export-filename="/home/luc/tmp/lstu-t/themes/default/public/img/mstile-lstu70.png"
inkscape:export-xdpi="17.75"
inkscape:export-ydpi="17.75"
inkscape:version="0.92.4 (5da689c313, 2019-01-14)"><metadata
id="metadata67"><rdf:RDF><cc:Work
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title></cc:Work></rdf:RDF></metadata><defs
id="defs65" /><sodipodi:namedview
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1"
objecttolerance="10"
gridtolerance="10"
guidetolerance="10"
inkscape:pageopacity="0"
inkscape:pageshadow="2"
inkscape:window-width="1918"
inkscape:window-height="1046"
id="namedview63"
showgrid="false"
inkscape:zoom="1.4517466"
inkscape:cx="81.606751"
inkscape:cy="118.64704"
inkscape:window-x="0"
inkscape:window-y="32"
inkscape:window-maximized="0"
inkscape:current-layer="layer3"
inkscape:pagecheckerboard="false" />
<g
inkscape:groupmode="layer"
id="layer2"
inkscape:label="Barbe"
style="display:inline"><g
id="g32"
transform="translate(35.902053,4.406215)">
<g
id="g30">
<g
id="g28">
<path
style="fill:#ff6a00"
d="M 188.60938 224.90625 L 188.60547 224.92773 C 180.04647 225.19673 131.24414 228.8603 132.61914 277.9043 C 134.12514 331.6503 170.96308 344.20727 186.70508 342.69727 C 187.63308 342.61227 190.97312 343.04678 193.32812 342.80078 C 209.81213 343.38178 244.43253 329.9673 245.89453 277.9043 C 247.27053 228.8603 198.45463 225.19673 189.89062 224.92773 L 189.88477 224.90625 C 189.88477 224.90625 189.66405 224.90706 189.24805 224.91406 C 188.83205 224.90706 188.60938 224.90625 188.60938 224.90625 z M 179.20898 255.79688 L 199.30664 255.79688 C 210.12464 255.79687 218.89453 264.56372 218.89453 275.38672 C 218.89453 286.20572 210.12464 294.97852 199.30664 294.97852 L 199.13281 294.97852 L 199.13281 288.28125 C 199.13281 282.82925 194.71091 278.40625 189.25391 278.40625 C 183.79891 278.40625 179.375 282.82925 179.375 288.28125 L 179.375 294.97852 L 179.20898 294.97852 C 168.38798 294.97852 159.61719 286.20472 159.61719 275.38672 C 159.61719 264.56372 168.38898 255.79688 179.20898 255.79688 z "
transform="translate(-35.902053,-4.406215)"
id="path26" />
</g>
</g>
</g><g
id="g44"
transform="translate(35.902053,4.406215)">
<path
style="fill:#b24b04"
inkscape:connector-curvature="0"
d="m 157.426,318.381 c -2.355,0.246 -5.695,-0.187 -6.623,-0.102 -14.828,1.422 -48.367,-9.643 -53.473,-55.847 -0.5,3.405 -0.725,7.083 -0.613,11.064 1.506,53.746 38.344,66.304 54.086,64.794 0.928,-0.085 4.268,0.348 6.623,0.102 16.484,0.581 51.104,-12.833 52.566,-64.896 0.111,-3.985 -0.113,-7.667 -0.615,-11.075 -4.935,44.675 -36.453,56.507 -51.951,55.96 z"
id="path42" />
</g><g
id="g52-0"
transform="translate(35.90205,4.4062134)"><g
id="g50-1"><g
id="g48-3" /></g></g></g><g
inkscape:groupmode="layer"
id="layer1"
inkscape:label="hat"><g
style=""
id="g8"
transform="translate(35.902053,4.406215)">
<g
id="g6">
<g
id="g4">
<path
style="fill:#231f20"
inkscape:connector-curvature="0"
d="m 235.405,144.066 h -164.1 v -33.467 c 0,-43.835 35.535,-79.37 79.371,-79.37 h 5.359 c 43.836,0 79.369,35.535 79.369,79.37 v 33.467 z"
id="path2" />
</g>
</g>
</g><g
style=""
id="g16"
transform="translate(35.902053,4.406215)">
<g
id="g14">
<g
id="g12">
<path
style="fill:#ffffff"
inkscape:connector-curvature="0"
d="m 122.516,75.256 c -12.99,7.393 -22.58,14.545 -27.373,11.127 -4.789,-3.415 -3.287,-16.879 11.949,-28.604 15.238,-11.729 30.242,-10.71 34.088,-5.591 4.479,5.957 -1.564,13.335 -18.664,23.068 z"
id="path10" />
</g>
</g>
</g><g
style=""
id="g24"
transform="translate(35.902053,4.406215)">
<g
id="g22">
<g
id="g20">
<path
style="fill:#231f20"
inkscape:connector-curvature="0"
d="m 264.145,166.489 c -15.203,-1.225 -64.404,-1.256 -110.791,-0.963 -46.383,-0.293 -95.588,-0.262 -110.793,0.963 -31.145,2.511 -19.09,35.165 -5.023,45.72 5.125,3.845 28.699,6.485 43.82,8.292 V 199.123 H 225.354 V 220.5 c 15.119,-1.807 38.691,-4.447 43.818,-8.292 14.065,-10.554 26.12,-43.208 -5.027,-45.719 z"
id="path18" />
</g>
</g>
</g></g><g
inkscape:groupmode="layer"
id="layer3"
inkscape:label="Bouche"
style="display:inline"><g
id="g60"
transform="translate(35.902053,4.406215)">
<g
id="g58">
<g
id="g56">
<path
style="fill:#231f20"
inkscape:connector-curvature="0"
d="m 168.956,266.961 h -31.203 c -2.217,0 -4.018,-1.799 -4.018,-4.018 0,-2.218 1.801,-4.016 4.018,-4.016 h 31.203 c 2.219,0 4.02,1.798 4.02,4.016 -0.001,2.22 -1.802,4.018 -4.02,4.018 z"
id="path54" />
</g>
</g>
</g></g></svg>

After

Width:  |  Height:  |  Size: 5.5 KiB

7
static/img/lufi.svg Normal file
View File

@ -0,0 +1,7 @@
<svg xmlns="http://www.w3.org/2000/svg" width="282.701" height="282.539">
<g transform="rotate(-45 -494.978 801.968) scale(1.41712)">
<path d="m214.91 548.044-38.638 1.01-2.273 6.566 3.03 3.03 41.922.758 157.078 1.01h40.154l5.303-5.303-2.778-6.819-19.698-1.01-20.203.252-2.778-15.404-6.818-16.92-14.395-17.93-13.637-12.628-13.132-6.566-18.183-5.303-22.728 1.263-21.213 4.798-13.385 5.556-13.132 10.86-10.606 13.384-7.324 9.343-3.788 10.355-3.283 12.879z" style="fill:#ffd119;fill-opacity:1;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"/>
<rect ry="7.321" y="522.79" x="216.173" height="24.244" width="159.857" style="fill:#ff000a;fill-opacity:1;fill-rule:evenodd;stroke:#000;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"/>
<path d="M191.541 487.67c-5.11-4.02-3.766-12.777 2.286-14.887 1.902-.663 9.868-1.135 19.14-1.135 11.858 0 15.967-.317 16.22-1.25.186-.688.813-3.788 1.393-6.89 3.712-19.86 19.217-41.972 37.206-53.061 24.328-14.997 56.897-16.927 82.61-4.895 23.515 11.004 42.69 34.144 48.048 57.981l1.782 7.932 18.368.341 17.104.342c9.452 1.084 8.29 17.087.242 17.5H314.998c-118.97 0-120.984-.032-123.457-1.978zm243.673-3.594c2.514-.828 3.439-3.94.372-6.228-2.53-1.886-29.037-1.2-120.465-1.2-116.89 0-119.286.038-120.3 1.934-1.406 2.628-1.307 3.652.536 5.494 1.411 1.411 13.665 1.572 119.929 1.572 106.264 0 116.732-.518 119.928-1.572zm-42.521-13.35c1.156-.731 1.21-1.87.302-6.392-.608-3.025-1.78-7.118-2.606-9.094l-1.501-3.592H239.813l-1.423 3.405c-1.945 4.656-3.88 14.34-3.113 15.58.797 1.29 155.382 1.381 157.416.094zm-25.907-24.391c0-1.247-5.704-11.732-7.623-14.014-2.888-3.434-3.053-5.673-.418-5.673 4.386 0 11.742 11.745 10.68 17.052l-.59 2.948h7.976c5.75 0 7.975-.352 7.975-1.26 0-2.268-8.582-14.11-14.606-20.155-15.054-15.107-33.863-22.606-56.602-22.568-22.088.038-39.402 6.88-54.364 21.483-6.946 6.78-15.428 18.41-15.428 21.155 0 1.112 10.65 1.345 61.5 1.345 33.825 0 61.5-.14 61.5-.313zm-93.592-3.065c-.662-1.726 3.908-10.693 6.77-13.283 1.633-1.479 2.069-1.515 3.272-.272 1.19 1.228.823 2.363-2.562 7.933-4.001 6.583-6.415 8.397-7.48 5.622zm74.817.128c-2.024-2.483-3.639-9.736-2.436-10.94 1.647-1.646 3.96.62 5.342 5.233 1.635 5.46-.188 9.04-2.906 5.707zm-87.873-3.275c-1.085-2.826 9.43-16.475 12.692-16.475 3.518 0 3.023 2.006-1.974 8.011-2.766 3.324-5.504 6.93-6.085 8.016-1.255 2.345-3.81 2.592-4.633.448zm27.069.18c-.662-1.724 2-6.22 4.177-7.054 2.192-.842 2.958 2.317 1.285 5.299-1.676 2.985-4.626 3.933-5.462 1.755z" style="fill:#000;fill-opacity:1" transform="translate(-17.8 72.845)"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 2.5 KiB

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="utf-8"?>
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="400" height="400">
<polygon id="b" points="0,0 400,0 0,400" style="fill:#000;" />
<polygon id="r" points="0,400 400,0 400,400" style="fill:#f00;" />
<g id="s" transform="translate(200,200)">
<path fill="#090" d="M-5.88,8.09 0,-10 5.88,8.09 -9.51,-3.09h19.02" transform="scale(16)"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 401 B

View File

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="400" height="400">
<title>Universal Libre Crypto-Libertarian Alternative</title>
<desc>
Alternative Libre Universelle Crypto-Libertaire
Universal Libre Crypto-Libertarian Alternative
Libera Universala KriptLiberecana Alternativo
License CC-0 (public domain)
</desc>
<polygon id="b" points="0,0 400,0 0,400" style="fill:#000;" />
<polygon id="r" points="0,400 400,0 400,400" style="fill:#f00;" />
<g id="s" transform="translate(200,200)">
<path fill="#090" d="M-5.88,8.09 0,-10 5.88,8.09 -9.51,-3.09h19.02" transform="scale(16)"/>
</g>
<g id="g" transform="translate(200,200) scale(2.5)">
<g id="a" transform="matrix(5.4506746,0,0,5.4506746,-76.785201,-29.5104) translate(-14.37,-44.6)">
<path id="v" style="fill:#fff;stroke:none" transform="scale(0.26458333)" d="m 109.55859,204.26455 h -3.86718 L 94.460937,176.74502 h 3.925782 l 7.617191,19.375 1.64062,4.86328 1.64063,-4.86328 7.57812,-19.375 h 3.92578 z" />
<path id="t" style="fill:#fff;stroke:none" transform="scale(0.87019766,1.1491642)" d="m 33.83541,42.892037 q -0.310284,0 -0.638556,-0.09893 -0.323775,-0.09893 -0.652046,-0.21585 -0.580097,-0.202359 -0.975821,-0.202359 -0.301291,0 -0.562109,0.09444 -0.260819,0.08994 -0.553115,0.30129 v -0.643053 q 0.499152,-0.377737 1.182677,-0.377737 0.233837,0 0.51714,0.05846 0.2878,0.05846 0.872393,0.265316 0.139403,0.05396 0.409215,0.130409 0.269812,0.07195 0.472172,0.07195 0.584593,0 1.097236,-0.413712 v 0.670034 q -0.260818,0.188868 -0.526134,0.274309 -0.260818,0.08544 -0.643052,0.08544 z" />
</g>
<g id="u" transform="translate(0,-30)">
<path fill="none" stroke-width="4" stroke="#fff" d="M-9,0 a8,8,0,0,0,18,0" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

28
static/img/lukla.svg Normal file
View File

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="600" height="400">
<title>Universal Libre Crypto-Libertarian Alternative</title>
<desc>
Alternative Libre Universelle Crypto-Libertaire
Universal Libre Crypto-Libertarian Alternative
Libera Universala KriptLiberecana Alternativo
License CC-0 (public domain)
</desc>
<polygon id="b" points="0,0 600,0 0,400" style="fill:#000;" />
<polygon id="r" points="0,400 600,0 600,400" style="fill:#f00;" />
<g id="s" transform="translate(300,200)">
<path fill="#090" d="M-5.88,8.09 0,-10 5.88,8.09 -9.51,-3.09h19.02" transform="scale(16)"/>
</g>
<g id="g" transform="translate(300,200) scale(2.5)">
<g id="a" transform="matrix(5.4506746,0,0,5.4506746,-76.785201,-29.5104) translate(-14.37,-44.6)">
<path id="v" style="fill:#fff;stroke:none" transform="scale(0.26458333)" d="m 109.55859,204.26455 h -3.86718 L 94.460937,176.74502 h 3.925782 l 7.617191,19.375 1.64062,4.86328 1.64063,-4.86328 7.57812,-19.375 h 3.92578 z" />
<path id="t" style="fill:#fff;stroke:none" transform="scale(0.87019766,1.1491642)" d="m 33.83541,42.892037 q -0.310284,0 -0.638556,-0.09893 -0.323775,-0.09893 -0.652046,-0.21585 -0.580097,-0.202359 -0.975821,-0.202359 -0.301291,0 -0.562109,0.09444 -0.260819,0.08994 -0.553115,0.30129 v -0.643053 q 0.499152,-0.377737 1.182677,-0.377737 0.233837,0 0.51714,0.05846 0.2878,0.05846 0.872393,0.265316 0.139403,0.05396 0.409215,0.130409 0.269812,0.07195 0.472172,0.07195 0.584593,0 1.097236,-0.413712 v 0.670034 q -0.260818,0.188868 -0.526134,0.274309 -0.260818,0.08544 -0.643052,0.08544 z" />
</g>
<g id="u" transform="translate(0,-30)">
<path fill="none" stroke-width="4" stroke="#fff" d="M-9,0 a8,8,0,0,0,18,0" />
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 1.7 KiB

BIN
static/img/lutim.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 50 KiB

View File

@ -0,0 +1,10 @@
<svg width="75" height="79" viewBox="0 0 75 79" fill="none" xmlns="http://www.w3.org/2000/svg">
<path d="M73.8393 17.4898C72.6973 9.00165 65.2994 2.31235 56.5296 1.01614C55.05 0.797115 49.4441 0 36.4582 0H36.3612C23.3717 0 20.585 0.797115 19.1054 1.01614C10.5798 2.27644 2.79399 8.28712 0.904997 16.8758C-0.00358524 21.1056 -0.100549 25.7949 0.0682394 30.0965C0.308852 36.2651 0.355538 42.423 0.91577 48.5665C1.30307 52.6474 1.97872 56.6957 2.93763 60.6812C4.73325 68.042 12.0019 74.1676 19.1233 76.6666C26.7478 79.2728 34.9474 79.7055 42.8039 77.9162C43.6682 77.7151 44.5217 77.4817 45.3645 77.216C47.275 76.6092 49.5123 75.9305 51.1571 74.7385C51.1797 74.7217 51.1982 74.7001 51.2112 74.6753C51.2243 74.6504 51.2316 74.6229 51.2325 74.5948V68.6416C51.2321 68.6154 51.2259 68.5896 51.2142 68.5661C51.2025 68.5426 51.1858 68.522 51.1651 68.5058C51.1444 68.4896 51.1204 68.4783 51.0948 68.4726C51.0692 68.4669 51.0426 68.467 51.0171 68.4729C45.9835 69.675 40.8254 70.2777 35.6502 70.2682C26.7439 70.2682 24.3486 66.042 23.6626 64.2826C23.1113 62.762 22.7612 61.1759 22.6212 59.5646C22.6197 59.5375 22.6247 59.5105 22.6357 59.4857C22.6466 59.4609 22.6633 59.4391 22.6843 59.422C22.7053 59.4048 22.73 59.3929 22.7565 59.3871C22.783 59.3813 22.8104 59.3818 22.8367 59.3886C27.7864 60.5826 32.8604 61.1853 37.9522 61.1839C39.1768 61.1839 40.3978 61.1839 41.6224 61.1516C46.7435 61.008 52.1411 60.7459 57.1796 59.7621C57.3053 59.7369 57.431 59.7154 57.5387 59.6831C65.4861 58.157 73.0493 53.3672 73.8178 41.2381C73.8465 40.7606 73.9184 36.2364 73.9184 35.7409C73.9219 34.0569 74.4606 23.7949 73.8393 17.4898Z" fill="url(#paint0_linear_549_34)"/>
<path d="M61.2484 27.0263V48.114H52.8916V27.6475C52.8916 23.3388 51.096 21.1413 47.4437 21.1413C43.4287 21.1413 41.4177 23.7409 41.4177 28.8755V40.0782H33.1111V28.8755C33.1111 23.7409 31.0965 21.1413 27.0815 21.1413C23.4507 21.1413 21.6371 23.3388 21.6371 27.6475V48.114H13.2839V27.0263C13.2839 22.7176 14.384 19.2946 16.5843 16.7572C18.8539 14.2258 21.8311 12.926 25.5264 12.926C29.8036 12.926 33.0357 14.5705 35.1905 17.8559L37.2698 21.346L39.3527 17.8559C41.5074 14.5705 44.7395 12.926 49.0095 12.926C52.7013 12.926 55.6784 14.2258 57.9553 16.7572C60.1531 19.2922 61.2508 22.7152 61.2484 27.0263Z" fill="white"/>
<defs>
<linearGradient id="paint0_linear_549_34" x1="37.0692" y1="0" x2="37.0692" y2="79" gradientUnits="userSpaceOnUse">
<stop stop-color="#6364FF"/>
<stop offset="1" stop-color="#563ACC"/>
</linearGradient>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 2.4 KiB

22
static/img/minetest.svg Normal file
View File

@ -0,0 +1,22 @@
<svg xmlns="http://www.w3.org/2000/svg" width="256" height="256" viewBox="0 0 48 48">
<path style="fill:#e9b96e;fill-opacity:1;stroke:#573a0d;stroke-width:1;stroke-linecap:square;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" d="M0 16v12l21.036 12.145 21-12.414V16.269L20.785 4 0 16z" transform="translate(3.464 6)"/>
<path style="fill:#2e3436;fill-opacity:1;stroke:#2e3436;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" d="m8.5 30.907-2-1.154v6L17.32 42v-2l-1.732-1v-2L13.5 35.794v-4l-5-2.887v2z"/>
<path style="opacity:1;fill:#555753;fill-opacity:1;stroke:#2e3436;stroke-linejoin:miter" d="m6.928 36 3.464-2 3.464 2 1.644.949v2l2 1.155v2L6.928 36z"/>
<path style="fill:#fce94f;fill-opacity:1;stroke:#625802;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" d="m25.98 19 5.52 3.187v2L38.094 28l3.468-2 3.938-2.27v2.54-4L32.909 15l-6.928 4z"/>
<path style="fill:#e9b96e;fill-opacity:1;stroke:#573a0d;stroke-width:1;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:.5" d="m24.84 18.341 8.66-5v2l-8.66 5v-2z"/>
<path style="fill:#73d216;fill-opacity:1;stroke:#325b09;stroke-width:1;stroke-linecap:square;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" d="M25.98 5 3.465 18 17.5 26.104l14-7.917-6.66-3.846 8.66-5L25.98 5z" transform="translate(0 4)"/>
<path style="fill:#729fcf;fill-opacity:1;stroke:#19314b;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" d="M17.5 28.104v2l1.553.896v2l5.447 3.145 12-7.072v-2.146l2-1.155v-1.544l-7-4.041-14 7.917z" transform="translate(0 4)"/>
<g style="stroke-linejoin:miter">
<path d="m13.856 20 6.929 4-6.929 4-6.928-4 6.928-4z" style="fill:#2e3436;fill-opacity:1;stroke:none;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0;filter:url(#filter3864);opacity:.25"/>
<g style="stroke-linejoin:miter">
<path style="fill:#c17d11;fill-opacity:1;stroke:#8f5902;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" d="m15.588 21 1.733 1 1.732-1v-6l-1.732-1-1.733 1v6z" transform="translate(-3.464 2)"/>
<path style="fill:#4e9a06;fill-opacity:1;stroke:#316004;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" d="M9.964 13.753 17.321 18l6.643-3.836V5.836L17.321 2 9.964 6.247v7.506z" transform="translate(-3.464 2)"/>
</g>
</g>
<g style="stroke-linejoin:miter">
<path transform="translate(24.249)" style="opacity:.25;fill:#2e3436;fill-opacity:1;stroke:none;filter:url(#filter3864);stroke-linejoin:miter" d="m13.856 20 5.197 3-5.197 3-5.196-3 5.196-3z"/>
<path style="fill:#4e9a06;fill-opacity:1;stroke:#316004;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:0" d="m15.715 21.073 1.606.927 1.394-.805v-8.39L17.321 12l-1.606 1.073v8z" transform="translate(20.785 2)"/>
</g>
<path style="fill:none;fill-opacity:1;stroke:#ef2929;stroke-width:.5;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:.5,.5;stroke-dashoffset:.25" d="m12.124 33-.866-.5"/>
<path style="fill:#888a85;stroke:#2e3436;stroke-width:1;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;stroke-dashoffset:.5" d="m45.5 26.73-4 2.31v1l-2 1.155v2l-2 1.154v4l8-4.618v-7z"/>
</svg>

After

Width:  |  Height:  |  Size: 3.8 KiB

201
static/img/mumble.svg Normal file
View File

@ -0,0 +1,201 @@
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="400" height="400" version="1.0">
<defs>
<linearGradient id="J">
<stop style="stop-color:#000;stop-opacity:0" offset="0"/>
<stop offset=".817" style="stop-color:#000;stop-opacity:.01960784"/>
<stop style="stop-color:#000;stop-opacity:.14509804" offset=".899"/>
<stop offset=".912" style="stop-color:#000;stop-opacity:.20784314"/>
<stop style="stop-color:#000;stop-opacity:.25098039" offset=".956"/>
<stop style="stop-color:#000;stop-opacity:.33333334" offset="1"/>
</linearGradient>
<linearGradient id="I">
<stop style="stop-color:#b3b3b3;stop-opacity:1" offset="0"/>
<stop style="stop-color:#b3b3b3;stop-opacity:0" offset="1"/>
</linearGradient>
<linearGradient id="G">
<stop style="stop-color:#000;stop-opacity:1" offset="0"/>
<stop style="stop-color:#000;stop-opacity:0" offset="1"/>
</linearGradient>
<linearGradient id="s">
<stop style="stop-color:#fff;stop-opacity:1" offset="0"/>
<stop style="stop-color:#fff;stop-opacity:0" offset="1"/>
</linearGradient>
<linearGradient id="j">
<stop style="stop-color:#b4b4b4;stop-opacity:1" offset="0"/>
<stop style="stop-color:#b3b3b3;stop-opacity:0" offset="1"/>
</linearGradient>
<linearGradient id="e">
<stop style="stop-color:#afafaf;stop-opacity:1" offset="0"/>
<stop style="stop-color:#e6e6e6;stop-opacity:0" offset="1"/>
</linearGradient>
<linearGradient id="d">
<stop style="stop-color:#afafaf;stop-opacity:1" offset="0"/>
<stop style="stop-color:#e6e6e6;stop-opacity:0" offset="1"/>
</linearGradient>
<linearGradient id="a">
<stop style="stop-color:#999;stop-opacity:1" offset="0"/>
<stop style="stop-color:#999;stop-opacity:0" offset="1"/>
</linearGradient>
<linearGradient id="b">
<stop style="stop-color:#b3b3b3;stop-opacity:1" offset="0"/>
<stop style="stop-color:#b3b3b3;stop-opacity:0" offset="1"/>
</linearGradient>
<linearGradient id="c">
<stop style="stop-color:gray;stop-opacity:1" offset="0"/>
<stop style="stop-color:gray;stop-opacity:0" offset="1"/>
</linearGradient>
<linearGradient id="f">
<stop style="stop-color:#b3b3b3;stop-opacity:1" offset="0"/>
<stop style="stop-color:#b3b3b3;stop-opacity:0" offset="1"/>
</linearGradient>
<linearGradient id="g">
<stop style="stop-color:#e6e6e6;stop-opacity:1" offset="0"/>
<stop style="stop-color:#e6e6e6;stop-opacity:0" offset="1"/>
</linearGradient>
<linearGradient id="h">
<stop style="stop-color:#afafaf;stop-opacity:1" offset="0"/>
<stop style="stop-color:#e6e6e6;stop-opacity:0" offset="1"/>
</linearGradient>
<linearGradient id="i">
<stop style="stop-color:#afafaf;stop-opacity:1" offset="0"/>
<stop style="stop-color:#e6e6e6;stop-opacity:0" offset="1"/>
</linearGradient>
<linearGradient id="k">
<stop style="stop-color:#999;stop-opacity:1" offset="0"/>
<stop style="stop-color:#999;stop-opacity:0" offset="1"/>
</linearGradient>
<linearGradient id="l">
<stop style="stop-color:#969696;stop-opacity:1" offset="0"/>
<stop style="stop-color:#e6e6e6;stop-opacity:0" offset="1"/>
</linearGradient>
<linearGradient id="m">
<stop style="stop-color:#afafaf;stop-opacity:1" offset="0"/>
<stop style="stop-color:#e6e6e6;stop-opacity:0" offset="1"/>
</linearGradient>
<linearGradient id="n">
<stop style="stop-color:#afafaf;stop-opacity:1" offset="0"/>
<stop style="stop-color:#e6e6e6;stop-opacity:0" offset="1"/>
</linearGradient>
<linearGradient id="o">
<stop style="stop-color:#afafaf;stop-opacity:1" offset="0"/>
<stop style="stop-color:#e6e6e6;stop-opacity:0" offset="1"/>
</linearGradient>
<linearGradient id="p">
<stop style="stop-color:#bebebe;stop-opacity:1" offset="0"/>
<stop style="stop-color:#b3b3b3;stop-opacity:0" offset="1"/>
</linearGradient>
<linearGradient id="q">
<stop style="stop-color:#afafaf;stop-opacity:1" offset="0"/>
<stop style="stop-color:#e6e6e6;stop-opacity:0" offset="1"/>
</linearGradient>
<linearGradient id="r">
<stop style="stop-color:#969696;stop-opacity:1" offset="0"/>
<stop style="stop-color:#e6e6e6;stop-opacity:0" offset="1"/>
</linearGradient>
<linearGradient id="t">
<stop style="stop-color:#fff;stop-opacity:1" offset="0"/>
<stop style="stop-color:#fff;stop-opacity:0" offset="1"/>
</linearGradient>
<linearGradient id="u">
<stop style="stop-color:#fff;stop-opacity:1" offset="0"/>
<stop style="stop-color:#fff;stop-opacity:0" offset="1"/>
</linearGradient>
<linearGradient id="v">
<stop style="stop-color:#fff;stop-opacity:1" offset="0"/>
<stop style="stop-color:#fff;stop-opacity:0" offset="1"/>
</linearGradient>
<linearGradient id="w">
<stop style="stop-color:#fff;stop-opacity:1" offset="0"/>
<stop style="stop-color:#fff;stop-opacity:0" offset="1"/>
</linearGradient>
<linearGradient id="x">
<stop style="stop-color:#fff;stop-opacity:1" offset="0"/>
<stop style="stop-color:#fff;stop-opacity:0" offset="1"/>
</linearGradient>
<linearGradient id="y">
<stop style="stop-color:#fff;stop-opacity:1" offset="0"/>
<stop style="stop-color:#fff;stop-opacity:0" offset="1"/>
</linearGradient>
<linearGradient id="z">
<stop style="stop-color:#fff;stop-opacity:1" offset="0"/>
<stop style="stop-color:#fff;stop-opacity:0" offset="1"/>
</linearGradient>
<linearGradient id="A">
<stop style="stop-color:#fff;stop-opacity:1" offset="0"/>
<stop style="stop-color:#fff;stop-opacity:0" offset="1"/>
</linearGradient>
<linearGradient id="B">
<stop style="stop-color:#fff;stop-opacity:1" offset="0"/>
<stop style="stop-color:#fff;stop-opacity:0" offset="1"/>
</linearGradient>
<linearGradient id="C">
<stop style="stop-color:#4d4d4d;stop-opacity:1" offset="0"/>
<stop style="stop-color:#4d4d4d;stop-opacity:0" offset="1"/>
</linearGradient>
<linearGradient id="D">
<stop style="stop-color:#fff;stop-opacity:1" offset="0"/>
<stop style="stop-color:#fff;stop-opacity:0" offset="1"/>
</linearGradient>
<linearGradient id="E">
<stop style="stop-color:#fff;stop-opacity:1" offset="0"/>
<stop style="stop-color:#fff;stop-opacity:0" offset="1"/>
</linearGradient>
<linearGradient id="F">
<stop style="stop-color:#fff;stop-opacity:1" offset="0"/>
<stop style="stop-color:#fff;stop-opacity:1" offset="1"/>
</linearGradient>
<linearGradient id="H">
<stop style="stop-color:#000;stop-opacity:1" offset="0"/>
<stop style="stop-color:#000;stop-opacity:0" offset="1"/>
</linearGradient>
<radialGradient xlink:href="#g" id="L" cx="333.528" cy="217.583" fx="333.528" fy="217.583" r="29.875" gradientTransform="matrix(-.95122 -.37973 -.79005 1.97905 561.776 -104.776)" gradientUnits="userSpaceOnUse"/>
<radialGradient xlink:href="#k" id="R" cx="172.614" cy="303.206" fx="172.614" fy="303.206" r="22.63" gradientTransform="matrix(1 0 0 .63329 0 119.5)" gradientUnits="userSpaceOnUse"/>
<radialGradient xlink:href="#l" id="S" cx="335.086" cy="219.037" fx="335.086" fy="219.037" r="29.875" gradientTransform="matrix(.5466 -.2774 .6405 1.262 11.608 18.445)" gradientUnits="userSpaceOnUse"/>
<radialGradient r="38.625" fy="25.979" fx="250.46" cy="25.979" cx="250.46" gradientTransform="matrix(-1.18645 .79501 .2118 .3161 435.388 -174.971)" gradientUnits="userSpaceOnUse" id="Q" xlink:href="#n"/>
<radialGradient r="103.516" fy="230.123" fx="458.028" cy="230.123" cx="458.028" gradientTransform="matrix(.41734 -.01064 .00888 .3481 9.439 55.321)" gradientUnits="userSpaceOnUse" id="P" xlink:href="#p"/>
<radialGradient r="38.625" fy="25.979" fx="250.46" cy="25.979" cx="250.46" gradientTransform="matrix(1.18645 .79501 -.2118 .3161 -32.887 -175.817)" gradientUnits="userSpaceOnUse" id="T" xlink:href="#q"/>
<radialGradient r="29.875" fy="219.037" fx="335.086" cy="219.037" cx="335.086" gradientTransform="matrix(-.5466 -.2774 -.6405 1.262 394.971 17.34)" gradientUnits="userSpaceOnUse" id="U" xlink:href="#r"/>
<radialGradient xlink:href="#I" id="M" cx="171.234" cy="217.677" fx="171.234" fy="217.677" r="19.572" gradientTransform="matrix(1 0 0 1.2781 0 -60.535)" gradientUnits="userSpaceOnUse"/>
<radialGradient xlink:href="#I" id="N" cx="212.031" cy="217.677" fx="212.031" fy="217.677" r="16.494" gradientTransform="matrix(1 0 0 1.51661 0 -112.455)" gradientUnits="userSpaceOnUse"/>
<radialGradient xlink:href="#I" id="O" cx="248.859" cy="217.677" fx="248.859" fy="217.677" r="16.697" gradientTransform="matrix(1 0 0 1.49816 0 -108.439)" gradientUnits="userSpaceOnUse"/>
<radialGradient xlink:href="#J" id="K" cx="206.644" cy="214.435" fx="206.644" fy="214.435" r="190.25" gradientTransform="matrix(.97267 .01618 -.01666 .97474 9.219 2.074)" gradientUnits="userSpaceOnUse"/>
</defs>
<g style="display:inline">
<path style="fill:#1a1a1a;stroke:#000;stroke-width:4.57597017;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline" d="M385.625 214.435c0 96.123-80.133 174.047-178.981 174.047-98.849 0-178.981-77.924-178.981-174.047 0-96.124 80.132-174.048 178.98-174.048 98.85 0 178.982 77.924 178.982 174.048z" transform="matrix(1.0811 0 0 1.10435 -22.438 -34.386)"/>
<path style="opacity:.9;fill:#fff;stroke:none;display:inline" d="M385.625 214.435c0 96.123-80.133 174.047-178.981 174.047-98.849 0-178.981-77.924-178.981-174.047 0-96.124 80.132-174.048 178.98-174.048 98.85 0 178.982 77.924 178.982 174.048z" transform="matrix(1.04227 0 0 1.0695 -13.736 -29.618)"/>
<path style="fill:#fff;stroke:#333;stroke-width:1.41267002;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline" d="M385.625 214.435c0 96.123-80.133 174.047-178.981 174.047-98.849 0-178.981-77.924-178.981-174.047 0-96.124 80.132-174.048 178.98-174.048 98.85 0 178.982 77.924 178.982 174.048z" transform="matrix(1.06413 0 0 1.07868 -20.794 -31.718)"/>
<path style="fill:none;stroke:#000;stroke-width:1.83038807;stroke-linejoin:round;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none;display:inline" d="M385.625 214.435c0 96.123-80.133 174.047-178.981 174.047-98.849 0-178.981-77.924-178.981-174.047 0-96.124 80.132-174.048 178.98-174.048 98.85 0 178.982 77.924 178.982 174.048z" transform="matrix(1.08566 0 0 1.109 -24.345 -36.155)"/>
</g>
<g style="display:inline">
<path style="opacity:.75;fill:url(#K);fill-opacity:1;stroke:none;display:inline" d="M385.625 214.435a178.981 174.047 0 1 1-357.962 0 178.981 174.047 0 1 1 357.962 0z" transform="matrix(1.0765 0 0 1.10093 -20.514 -34.696)"/>
</g>
<g style="display:inline">
<path style="fill:#000;fill-opacity:1;fill-rule:evenodd;stroke:#fff" d="M152.406 31.61c-24.651-.615-49.623 15.705-55.852 40.126-1.451 5.92-2.043 11.534-2.148 17.251v63.623h25c.088-22.382-.126-44.644.17-67.072.769-14.243 11.774-29.258 27.049-29.084.112 22.668-.23 45.351.18 68.01 1.303 18.427 18.762 33.677 37.243 32.115 11.546-.28 23.178.673 34.648-.725 17.466-3.274 29.553-21.063 27.929-38.45V56.548c15.888-1.16 27.938 14.264 28.642 29.085.295 22.427.083 44.692.17 67.072h25v-67.5c-.818-7.276-1.971-16.18-5.914-23.199-10.23-20.75-34.154-31.948-56.718-30.261-6.59-.837-13.681 3.62-15.487 9.867.109 26.738.186 53.486-.015 80.22-.753 11.2-11.79 19.763-22.805 18.342-7.792.338-16.594.013-21.908-6.682-7.163-7.57-4.763-18.406-5.184-27.812.02-21.719-.071-43.418.125-65.1-3.26-6.592-10.503-9.994-17.68-8.912l-1.187-.017-1.258-.04z" transform="matrix(1.05 0 0 1.05 -5.356 .51)"/>
<path style="opacity:.96660007;fill:url(#L);fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline" d="M107.27 156.262v177.843c-35.128-3.853-62.738-42.188-62.738-88.921 0-46.734 27.61-85.069 62.738-88.922z"/>
</g>
<g style="display:inline">
<path style="fill:#000;fill-opacity:1;fill-rule:evenodd;stroke:#fff" d="M290.424 313.156c-.699-.007-3.31-.575-3.94-.167 0 0-1.036 3.017-4.604 5.673-3.133 2.331-6.108 4.566-9.295 6.662-2.862 1.883-5.933 3.918-8.81 5.303-2.264 1.09-4.114 1.248-4.114 1.248h-32.22c-2.012 0-3.661 1.587-3.661 3.563v.875c0 1.975 1.649 3.593 3.662 3.593h33.879c.78 0 3.597-.82 5.272-1.555 4.177-1.833 6.9-4.166 11.71-7.027 5.115-3.272 14.573-10.886 14.573-10.886a3.512 3.512 0 0 0 1.019-4.938l-.478-.75a3.628 3.628 0 0 0-2.993-1.594z" transform="matrix(1.05 0 0 1.05 -5.356 .51)"/>
<path style="opacity:.96660007;fill:#000;fill-opacity:1;fill-rule:evenodd;stroke:#fff" d="M288.25 148.438v169.375c33.455-3.67 59.75-40.18 59.75-84.688s-26.295-81.018-59.75-84.688z" transform="matrix(1.05 0 0 1.05 -5.356 .51)"/>
<path style="opacity:.96660007;fill:#000;fill-opacity:1;fill-rule:evenodd;stroke:#fff;display:inline" d="M106.224 149.337v169.375c-33.456-3.67-59.75-40.179-59.75-84.687 0-44.508 26.294-81.018 59.75-84.688z" transform="matrix(1.05 0 0 1.05 -5.356 .51)"/>
<path style="opacity:.96660007;fill:#000;fill-opacity:1;fill-rule:evenodd;stroke:#fff" d="M194.744 325.864a22.13 13.831 0 1 1-44.26 0 22.13 13.831 0 1 1 44.26 0z" transform="matrix(1.30479 0 0 1.21464 -20.46 -43.8)"/>
<rect style="opacity:.96660007;fill:#000;fill-opacity:1;fill-rule:evenodd;stroke:#fff;stroke-width:1.05377054;display:inline" width="13.329" height="171.946" x="274.718" y="146.09" rx="3.888" ry="3.54" transform="matrix(1.04333 0 0 1.05002 -4.656 .095)"/>
<rect style="opacity:.96660007;fill:#000;fill-opacity:1;fill-rule:evenodd;stroke:#fff;stroke-width:1.04323161;display:inline" width="13.063" height="171.957" x="106.561" y="147.085" rx="3.81" ry="3.54" transform="matrix(1.04333 0 0 1.05002 -3.835 .095)"/>
</g>
<g style="display:inline">
<path style="fill:#000;fill-opacity:1;fill-rule:evenodd;stroke:none" d="M131.636 188.831h140.835v111.885H131.636z"/>
<path style="font-size:64px;font-style:normal;font-variant:normal;font-weight:700;font-stretch:normal;text-align:center;text-anchor:middle;fill:url(#M);fill-opacity:1;stroke:none;display:inline;font-family:Tahoma;-inkscape-font-specification:Tahoma Bold" d="M189.844 226.693c0 2.313-.438 4.344-1.313 6.094s-2.052 3.198-3.531 4.344a16.363 16.363 0 0 1-5.766 2.937c-2.093.583-4.755.875-7.984.875h-18.625v-46.531h16.438c3.416 0 6.005.13 7.765.39 1.76.26 3.412.808 4.953 1.641 1.667.896 2.912 2.094 3.735 3.594s1.234 3.23 1.234 5.187c0 2.271-.568 4.292-1.703 6.063-1.136 1.77-2.703 3.073-4.703 3.906v.25c2.875.604 5.177 1.839 6.906 3.703 1.73 1.865 2.594 4.38 2.594 7.547zm-14.969-19.125c0-.75-.193-1.52-.578-2.312a3.486 3.486 0 0 0-1.797-1.72c-.77-.332-1.682-.515-2.734-.546-1.052-.031-2.62-.047-4.703-.047h-.813v9.844h1.469c2 0 3.4-.021 4.203-.063.802-.041 1.63-.26 2.484-.656.938-.437 1.584-1.042 1.938-1.812.354-.771.531-1.667.531-2.688zm2.938 18.906c0-1.437-.292-2.562-.875-3.375-.584-.812-1.459-1.427-2.625-1.843-.709-.271-1.683-.422-2.922-.454-1.24-.03-2.901-.046-4.985-.046h-2.156v11.656h.625c3.042 0 5.146-.021 6.313-.063 1.166-.041 2.354-.323 3.562-.843 1.062-.459 1.839-1.13 2.328-2.016.49-.885.734-1.89.735-3.016z" transform="matrix(1.10072 0 0 2.00007 -23.812 -190.28)"/>
<path style="font-size:64px;font-style:normal;font-variant:normal;font-weight:700;font-stretch:normal;text-align:center;text-anchor:middle;fill:#fff;fill-opacity:1;stroke:none;font-family:Tahoma;-inkscape-font-specification:Tahoma Bold" d="M189.844 226.693c0 2.313-.438 4.344-1.313 6.094s-2.052 3.198-3.531 4.344a16.363 16.363 0 0 1-5.766 2.937c-2.093.583-4.755.875-7.984.875h-18.625v-46.531h16.438c3.416 0 6.005.13 7.765.39 1.76.26 3.412.808 4.953 1.641 1.667.896 2.912 2.094 3.735 3.594s1.234 3.23 1.234 5.187c0 2.271-.568 4.292-1.703 6.063-1.136 1.77-2.703 3.073-4.703 3.906v.25c2.875.604 5.177 1.839 6.906 3.703 1.73 1.865 2.594 4.38 2.594 7.547zm-14.969-19.125c0-.75-.193-1.52-.578-2.312a3.486 3.486 0 0 0-1.797-1.72c-.77-.332-1.682-.515-2.734-.546-1.052-.031-2.62-.047-4.703-.047h-.813v9.844h1.469c2 0 3.4-.021 4.203-.063.802-.041 1.63-.26 2.484-.656.938-.437 1.584-1.042 1.938-1.812.354-.771.531-1.667.531-2.688zm2.938 18.906c0-1.437-.292-2.562-.875-3.375-.584-.812-1.459-1.427-2.625-1.843-.709-.271-1.683-.422-2.922-.454-1.24-.03-2.901-.046-4.985-.046h-2.156v11.656h.625c3.042 0 5.146-.021 6.313-.063 1.166-.041 2.354-.323 3.562-.843 1.062-.459 1.839-1.13 2.328-2.016.49-.885.734-1.89.735-3.016z" transform="matrix(1.10072 0 0 2.00007 -28.29 -190.597)"/>
<path style="font-size:64px;font-style:normal;font-variant:normal;font-weight:700;font-stretch:normal;text-align:center;text-anchor:middle;fill:url(#N);fill-opacity:1;stroke:none;display:inline;font-family:Tahoma;-inkscape-font-specification:Tahoma Bold" d="M227.563 240.943H196.5v-46.531h11.688v37.656h19.375z" transform="matrix(1.10072 0 0 2.00007 -23.812 -190.28)"/>
<path style="fill:#fff;fill-opacity:1;stroke:none" d="M187.313 197.563v94.53h35.562v-19.25H201.5v-75.28h-14.188z"/>
<path style="font-size:64px;font-style:normal;font-variant:normal;font-weight:700;font-stretch:normal;text-align:center;text-anchor:middle;fill:url(#O);fill-opacity:1;stroke:none;display:inline;font-family:Tahoma;-inkscape-font-specification:Tahoma Bold" d="M233.125 240.943v-46.531h31.469v8.875H244.75v8.156h18.281v8.875H244.75v11.75h19.844v8.875z" transform="matrix(1.10072 0 0 2.00007 -23.812 -190.28)"/>
<path style="fill:#fff;fill-opacity:1;stroke:none;display:inline" d="M227.813 197.5v94.531h35.562v-19.25H242V250.5h19.656v-18.656H242V216.75h21.375V197.5h-35.563z"/>
</g>
<g style="display:inline">
<path style="fill:url(#P);fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline" d="M155.37 33.01c-25.884-.646-52.104 16.49-58.645 42.133-1.524 6.216-2.145 12.11-2.255 18.113v66.804h26.25c.092-23.501-.133-46.876.178-70.425.807-14.956 12.362-30.722 28.401-30.539.118 23.802-.24 47.619.19 71.412 1.367 19.347 19.7 35.36 39.105 33.72 12.123-.295 24.337.706 36.38-.762 18.339-3.438 31.03-22.115 29.325-40.372v-63.9c16.683-1.218 29.335 14.977 30.075 30.539.31 23.549.086 46.927.179 70.426h26.25V89.284c-.86-7.64-2.07-16.99-6.211-24.359-10.74-21.789-35.861-33.545-59.553-31.774-6.921-.88-14.366 3.8-16.262 10.36.115 28.075.195 56.16-.015 84.23-.791 11.76-12.38 20.753-23.946 19.26-8.182.355-17.423.014-23.004-7.016-7.52-7.949-5-19.326-5.442-29.202.02-22.805-.075-45.59.13-68.356-3.422-6.92-11.027-10.493-18.562-9.357l-1.247-.017-1.321-.043z"/>
<path style="fill:url(#Q);fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline" d="M154.532 34.269c-31.655 0-56.169 21.233-59.981 48.759h26.972c3.644-12.426 13.113-21.517 24.51-22.575a4.247 4.247 0 0 1 2.92-1.148h26.612l.098-15.62s-2.378-3.724-4.298-5.479c-2.176-1.988-5.112-3.428-8.007-3.74-2.425-.262-5.2-.042-8.826-.197z"/>
<path style="opacity:.96660007;fill:url(#R);fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline" d="M194.744 325.864a22.13 13.831 0 1 1-44.26 0 22.13 13.831 0 1 1 44.26 0z" transform="matrix(1.30479 0 0 1.21464 -20.434 -43.907)"/>
<path style="opacity:.96660007;fill:url(#S);fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline" d="M298.657 157.256V335.1c35.128-3.854 62.737-42.189 62.737-88.922 0-46.734-27.609-85.069-62.737-88.922z"/>
<path style="fill:url(#T);fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline" d="M247.969 33.422c31.655 0 56.169 21.234 59.981 48.76h-26.972c-3.644-12.426-13.113-21.518-24.51-22.575a4.247 4.247 0 0 0-2.92-1.149h-26.612l-.098-15.619s2.378-3.725 4.298-5.48c2.176-1.987 5.112-3.428 8.007-3.74 2.425-.262 5.2-.041 8.826-.197z"/>
<path style="opacity:.96660007;fill:url(#U);fill-opacity:1;fill-rule:evenodd;stroke:none;display:inline" d="M107.922 156.152v177.844c-35.128-3.854-62.738-42.188-62.738-88.922 0-46.734 27.61-85.069 62.738-88.922z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 19 KiB

3
static/img/nextcloud.svg Normal file
View File

@ -0,0 +1,3 @@
<svg width="256" height="256" viewBox="0 -64 256 256" xmlns="http://www.w3.org/2000/svg">
<path d="M128 7c-25.871 0-47.817 17.485-54.713 41.209C67.307 35.748 54.645 27 40 27 19.696 27 3 43.696 3 64s16.696 37 37 37c14.645 0 27.308-8.748 33.287-21.209C80.183 103.515 102.129 121 128 121s47.817-17.485 54.713-41.209C188.693 92.252 201.355 101 216 101c20.304 0 37-16.696 37-37s-16.696-37-37-37c-14.645 0-27.308 8.748-33.287 21.209C175.817 24.485 153.871 7 128 7zm0 22c19.46 0 35 15.54 35 35s-15.54 35-35 35-35-15.54-35-35 15.54-35 35-35zM40 49c8.415 0 15 6.585 15 15s-6.585 15-15 15-15-6.585-15-15 6.585-15 15-15zm176 0c8.415 0 15 6.585 15 15s-6.585 15-15 15-15-6.585-15-15 6.585-15 15-15z" fill="#f80"/>
</svg>

After

Width:  |  Height:  |  Size: 709 B

6
static/img/peertube.svg Normal file
View File

@ -0,0 +1,6 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="2799 -911 16 22">
<path fill="#211f20" d="M2799-911v11l8-5" data-name="Path 4"/>
<path fill="#737373" d="M2799-900v11l8-6" data-name="Path 5"/>
<path fill="#f1680d" d="M2807-905v10l8-5" data-name="Path 6"/>
<path fill="transparent" d="M2807-895v-10l-8 5z" data-name="Path 7"/>
</svg>

After

Width:  |  Height:  |  Size: 337 B

BIN
static/img/progaccess.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 41 KiB

69
static/img/syeve.svg Normal file
View File

@ -0,0 +1,69 @@
<svg viewBox="-16 -16 32 32" xmlns="http://www.w3.org/2000/svg">
<mask id="round">
<circle cx="0" cy="0" r="16" fill="#fff"/>
</mask>
<g mask="url(#round)">
<g transform="translate(0,-16)">
<rect x="-16" y="0" width="4" height="4" fill="#000"/>
<rect x="-12" y="0" width="4" height="4" fill="#fff"/>
<rect x="-8" y="0" width="4" height="4" fill="#000"/>
<rect x="-4" y="0" width="4" height="4" fill="#fff"/>
<rect x="0" y="0" width="4" height="4" fill="#fff"/>
<rect x="4" y="0" width="4" height="4" fill="#000"/>
<rect x="8" y="0" width="4" height="4" fill="#fff"/>
<rect x="12" y="0" width="4" height="4" fill="#000"/>
</g>
<g transform="translate(0,-12)">
<rect x="-16" y="0" width="4" height="4" fill="#f0f"/>
<rect x="-12" y="0" width="4" height="4" fill="#0ff"/>
<rect x="-8" y="0" width="4" height="4" fill="#ff0"/>
<rect x="-4" y="0" width="4" height="4" fill="#0ff"/>
<rect x="0" y="0" width="4" height="4" fill="#f0f"/>
<rect x="4" y="0" width="4" height="4" fill="#0ff"/>
<rect x="8" y="0" width="4" height="4" fill="#ff0"/>
<rect x="12" y="0" width="4" height="4" fill="#f0f"/>
</g>
<g transform="translate(0,-8)">
<rect x="-16" y="0" width="4" height="4" fill="#111"/>
<rect x="-12" y="0" width="4" height="4" fill="#333"/>
<rect x="-8" y="0" width="4" height="4" fill="#555"/>
<rect x="-4" y="0" width="4" height="4" fill="#666"/>
<rect x="0" y="0" width="4" height="4" fill="#888"/>
<rect x="4" y="0" width="4" height="4" fill="#aaa"/>
<rect x="8" y="0" width="4" height="4" fill="#ccc"/>
<rect x="12" y="0" width="4" height="4" fill="#eee"/>
</g>
<g transform="translate(0,-4)">
<rect x="-16" y="0" width="8" height="4" fill="#fff"/>
<rect x="-8" y="0" width="8" height="4" fill="#bbb"/>
<rect x="0" y="0" width="8" height="4" fill="#444"/>
<rect x="8" y="0" width="8" height="4" fill="#000"/>
</g>
<g transform="translate(0,0)">
<rect x="-16" y="0" width="4" height="4" fill="#0ff"/>
<rect x="-12" y="0" width="4" height="4" fill="#f0f"/>
<rect x="-8" y="0" width="4" height="4" fill="#ff0"/>
<rect x="-4" y="0" width="4" height="4" fill="#f0f"/>
<rect x="0" y="0" width="4" height="4" fill="#0ff"/>
<rect x="4" y="0" width="4" height="4" fill="#f0f"/>
<rect x="8" y="0" width="4" height="4" fill="#ff0"/>
<rect x="12" y="0" width="4" height="4" fill="#f0f"/>
</g>
<g transform="translate(0,4)">
<rect x="-16" y="0" width="4" height="4" fill="#00f"/>
<rect x="-12" y="0" width="4" height="4" fill="#0f0"/>
<rect x="-8" y="0" width="4" height="4" fill="#0f0"/>
<rect x="-4" y="0" width="4" height="4" fill="#00f"/>
<rect x="0" y="0" width="4" height="4" fill="#00f"/>
<rect x="4" y="0" width="4" height="4" fill="#f00"/>
<rect x="8" y="0" width="4" height="4" fill="#f00"/>
<rect x="12" y="0" width="4" height="4" fill="#00f"/>
</g>
<rect x="-16" y="8" width="32" height="8" fill="#fff"/>
<path d="M8,4 L8,0 Q15,-5 5,-13 Q0,-17 0,-25 Q0,-17 -5,-13 Q-15,-5 -8,0 L-8,4 Z" fill="#000" transform="translate(0,12)"/>
<g transform="translate(0,4)">
<circle cx="-4" cy="0" r="1" fill="#fff"/>
<circle cx="4" cy="0" r="1" fill="#fff"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 3.2 KiB

119
static/katex/README.md Normal file
View File

@ -0,0 +1,119 @@
# [<img src="https://katex.org/img/katex-logo-black.svg" width="130" alt="KaTeX">](https://katex.org/)
[![npm](https://img.shields.io/npm/v/katex.svg)](https://www.npmjs.com/package/katex)
[![semantic-release](https://img.shields.io/badge/%20%20%F0%9F%93%A6%F0%9F%9A%80-semantic--release-e10079.svg)](https://github.com/semantic-release/semantic-release)
[![CI](https://github.com/KaTeX/KaTeX/workflows/CI/badge.svg?branch=main&event=push)](https://github.com/KaTeX/KaTeX/actions?query=workflow%3ACI)
[![codecov](https://codecov.io/gh/KaTeX/KaTeX/branch/main/graph/badge.svg)](https://codecov.io/gh/KaTeX/KaTeX)
[![Discussions](https://img.shields.io/badge/Discussions-join-brightgreen)](https://github.com/KaTeX/KaTeX/discussions)
[![jsDelivr](https://data.jsdelivr.com/v1/package/npm/katex/badge?style=rounded)](https://www.jsdelivr.com/package/npm/katex)
![katex.min.js size](https://img.badgesize.io/https://unpkg.com/katex/dist/katex.min.js?compression=gzip)
[![Gitpod ready-to-code](https://img.shields.io/badge/Gitpod-ready--to--code-blue?logo=gitpod)](https://gitpod.io/#https://github.com/KaTeX/KaTeX)
[![Financial Contributors on Open Collective](https://opencollective.com/katex/all/badge.svg?label=financial+contributors)](https://opencollective.com/katex)
KaTeX is a fast, easy-to-use JavaScript library for TeX math rendering on the web.
* **Fast:** KaTeX renders its math synchronously and doesn't need to reflow the page. See how it compares to a competitor in [this speed test](http://www.intmath.com/cg5/katex-mathjax-comparison.php).
* **Print quality:** KaTeX's layout is based on Donald Knuth's TeX, the gold standard for math typesetting.
* **Self contained:** KaTeX has no dependencies and can easily be bundled with your website resources.
* **Server side rendering:** KaTeX produces the same output regardless of browser or environment, so you can pre-render expressions using Node.js and send them as plain HTML.
KaTeX is compatible with all major browsers, including Chrome, Safari, Firefox, Opera, Edge, and IE 11.
KaTeX supports much (but not all) of LaTeX and many LaTeX packages. See the [list of supported functions](https://katex.org/docs/supported.html).
Try out KaTeX [on the demo page](https://katex.org/#demo)!
## Getting started
### Starter template
```html
<!DOCTYPE html>
<!-- KaTeX requires the use of the HTML5 doctype. Without it, KaTeX may not render properly -->
<html>
<head>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/katex@0.15.2/dist/katex.min.css" integrity="sha384-MlJdn/WNKDGXveldHDdyRP1R4CTHr3FeuDNfhsLPYrq2t0UBkUdK2jyTnXPEK1NQ" crossorigin="anonymous">
<!-- The loading of KaTeX is deferred to speed up page rendering -->
<script defer src="https://cdn.jsdelivr.net/npm/katex@0.15.2/dist/katex.min.js" integrity="sha384-VQ8d8WVFw0yHhCk5E8I86oOhv48xLpnDZx5T9GogA/Y84DcCKWXDmSDfn13bzFZY" crossorigin="anonymous"></script>
<!-- To automatically render math in text elements, include the auto-render extension: -->
<script defer src="https://cdn.jsdelivr.net/npm/katex@0.15.2/dist/contrib/auto-render.min.js" integrity="sha384-+XBljXPPiv+OzfbB3cVmLHf4hdUFHlWNZN5spNQ7rmHTXpd7WvJum6fIACpNNfIR" crossorigin="anonymous"
onload="renderMathInElement(document.body);"></script>
</head>
...
</html>
```
You can also [download KaTeX](https://github.com/KaTeX/KaTeX/releases) and host it yourself.
For details on how to configure auto-render extension, refer to [the documentation](https://katex.org/docs/autorender.html).
### API
Call `katex.render` to render a TeX expression directly into a DOM element.
For example:
```js
katex.render("c = \\pm\\sqrt{a^2 + b^2}", element, {
throwOnError: false
});
```
Call `katex.renderToString` to generate an HTML string of the rendered math,
e.g., for server-side rendering. For example:
```js
var html = katex.renderToString("c = \\pm\\sqrt{a^2 + b^2}", {
throwOnError: false
});
// '<span class="katex">...</span>'
```
Make sure to include the CSS and font files in both cases.
If you are doing all rendering on the server, there is no need to include the
JavaScript on the client.
The examples above use the `throwOnError: false` option, which renders invalid
inputs as the TeX source code in red (by default), with the error message as
hover text. For other available options, see the
[API documentation](https://katex.org/docs/api.html),
[options documentation](https://katex.org/docs/options.html), and
[handling errors documentation](https://katex.org/docs/error.html).
## Demo and Documentation
Learn more about using KaTeX [on the website](https://katex.org)!
## Contributors
### Code Contributors
This project exists thanks to all the people who contribute code. If you'd like to help, see [our guide to contributing code](CONTRIBUTING.md).
<a href="https://github.com/KaTeX/KaTeX/graphs/contributors"><img src="https://contributors-svg.opencollective.com/katex/contributors.svg?width=890&button=false" alt="Code contributors" /></a>
### Financial Contributors
Become a financial contributor and help us sustain our community.
#### Individuals
<a href="https://opencollective.com/katex"><img src="https://opencollective.com/katex/individuals.svg?width=890" alt="Contribute on Open Collective"></a>
#### Organizations
Support this project with your organization. Your logo will show up here with a link to your website.
<a href="https://opencollective.com/katex/organization/0/website"><img src="https://opencollective.com/katex/organization/0/avatar.svg" alt="Organization 1"></a>
<a href="https://opencollective.com/katex/organization/1/website"><img src="https://opencollective.com/katex/organization/1/avatar.svg" alt="Organization 2"></a>
<a href="https://opencollective.com/katex/organization/2/website"><img src="https://opencollective.com/katex/organization/2/avatar.svg" alt="Organization 3"></a>
<a href="https://opencollective.com/katex/organization/3/website"><img src="https://opencollective.com/katex/organization/3/avatar.svg" alt="Organization 4"></a>
<a href="https://opencollective.com/katex/organization/4/website"><img src="https://opencollective.com/katex/organization/4/avatar.svg" alt="Organization 5"></a>
<a href="https://opencollective.com/katex/organization/5/website"><img src="https://opencollective.com/katex/organization/5/avatar.svg" alt="Organization 6"></a>
<a href="https://opencollective.com/katex/organization/6/website"><img src="https://opencollective.com/katex/organization/6/avatar.svg" alt="Organization 7"></a>
<a href="https://opencollective.com/katex/organization/7/website"><img src="https://opencollective.com/katex/organization/7/avatar.svg" alt="Organization 8"></a>
<a href="https://opencollective.com/katex/organization/8/website"><img src="https://opencollective.com/katex/organization/8/avatar.svg" alt="Organization 9"></a>
<a href="https://opencollective.com/katex/organization/9/website"><img src="https://opencollective.com/katex/organization/9/avatar.svg" alt="Organization 10"></a>
## License
KaTeX is licensed under the [MIT License](http://opensource.org/licenses/MIT).

View File

@ -0,0 +1,327 @@
(function webpackUniversalModuleDefinition(root, factory) {
if(typeof exports === 'object' && typeof module === 'object')
module.exports = factory(require("katex"));
else if(typeof define === 'function' && define.amd)
define(["katex"], factory);
else if(typeof exports === 'object')
exports["renderMathInElement"] = factory(require("katex"));
else
root["renderMathInElement"] = factory(root["katex"]);
})((typeof self !== 'undefined' ? self : this), function(__WEBPACK_EXTERNAL_MODULE__771__) {
return /******/ (function() { // webpackBootstrap
/******/ "use strict";
/******/ var __webpack_modules__ = ({
/***/ 771:
/***/ (function(module) {
module.exports = __WEBPACK_EXTERNAL_MODULE__771__;
/***/ })
/******/ });
/************************************************************************/
/******/ // The module cache
/******/ var __webpack_module_cache__ = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/ // Check if module is in cache
/******/ var cachedModule = __webpack_module_cache__[moduleId];
/******/ if (cachedModule !== undefined) {
/******/ return cachedModule.exports;
/******/ }
/******/ // Create a new module (and put it into the cache)
/******/ var module = __webpack_module_cache__[moduleId] = {
/******/ // no module.id needed
/******/ // no module.loaded needed
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__);
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/************************************************************************/
/******/ /* webpack/runtime/compat get default export */
/******/ !function() {
/******/ // getDefaultExport function for compatibility with non-harmony modules
/******/ __webpack_require__.n = function(module) {
/******/ var getter = module && module.__esModule ?
/******/ function() { return module['default']; } :
/******/ function() { return module; };
/******/ __webpack_require__.d(getter, { a: getter });
/******/ return getter;
/******/ };
/******/ }();
/******/
/******/ /* webpack/runtime/define property getters */
/******/ !function() {
/******/ // define getter functions for harmony exports
/******/ __webpack_require__.d = function(exports, definition) {
/******/ for(var key in definition) {
/******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
/******/ }
/******/ }
/******/ };
/******/ }();
/******/
/******/ /* webpack/runtime/hasOwnProperty shorthand */
/******/ !function() {
/******/ __webpack_require__.o = function(obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); }
/******/ }();
/******/
/************************************************************************/
var __webpack_exports__ = {};
// This entry need to be wrapped in an IIFE because it need to be isolated against other modules in the chunk.
!function() {
// EXPORTS
__webpack_require__.d(__webpack_exports__, {
"default": function() { return /* binding */ auto_render; }
});
// EXTERNAL MODULE: external "katex"
var external_katex_ = __webpack_require__(771);
var external_katex_default = /*#__PURE__*/__webpack_require__.n(external_katex_);
;// CONCATENATED MODULE: ./contrib/auto-render/splitAtDelimiters.js
/* eslint no-constant-condition:0 */
var findEndOfMath = function findEndOfMath(delimiter, text, startIndex) {
// Adapted from
// https://github.com/Khan/perseus/blob/master/src/perseus-markdown.jsx
var index = startIndex;
var braceLevel = 0;
var delimLength = delimiter.length;
while (index < text.length) {
var character = text[index];
if (braceLevel <= 0 && text.slice(index, index + delimLength) === delimiter) {
return index;
} else if (character === "\\") {
index++;
} else if (character === "{") {
braceLevel++;
} else if (character === "}") {
braceLevel--;
}
index++;
}
return -1;
};
var escapeRegex = function escapeRegex(string) {
return string.replace(/[-/\\^$*+?.()|[\]{}]/g, "\\$&");
};
var amsRegex = /^\\begin{/;
var splitAtDelimiters = function splitAtDelimiters(text, delimiters) {
var index;
var data = [];
var regexLeft = new RegExp("(" + delimiters.map(function (x) {
return escapeRegex(x.left);
}).join("|") + ")");
while (true) {
index = text.search(regexLeft);
if (index === -1) {
break;
}
if (index > 0) {
data.push({
type: "text",
data: text.slice(0, index)
});
text = text.slice(index); // now text starts with delimiter
} // ... so this always succeeds:
var i = delimiters.findIndex(function (delim) {
return text.startsWith(delim.left);
});
index = findEndOfMath(delimiters[i].right, text, delimiters[i].left.length);
if (index === -1) {
break;
}
var rawData = text.slice(0, index + delimiters[i].right.length);
var math = amsRegex.test(rawData) ? rawData : text.slice(delimiters[i].left.length, index);
data.push({
type: "math",
data: math,
rawData: rawData,
display: delimiters[i].display
});
text = text.slice(index + delimiters[i].right.length);
}
if (text !== "") {
data.push({
type: "text",
data: text
});
}
return data;
};
/* harmony default export */ var auto_render_splitAtDelimiters = (splitAtDelimiters);
;// CONCATENATED MODULE: ./contrib/auto-render/auto-render.js
/* eslint no-console:0 */
/* Note: optionsCopy is mutated by this method. If it is ever exposed in the
* API, we should copy it before mutating.
*/
var renderMathInText = function renderMathInText(text, optionsCopy) {
var data = auto_render_splitAtDelimiters(text, optionsCopy.delimiters);
if (data.length === 1 && data[0].type === 'text') {
// There is no formula in the text.
// Let's return null which means there is no need to replace
// the current text node with a new one.
return null;
}
var fragment = document.createDocumentFragment();
for (var i = 0; i < data.length; i++) {
if (data[i].type === "text") {
fragment.appendChild(document.createTextNode(data[i].data));
} else {
var span = document.createElement("span");
var math = data[i].data; // Override any display mode defined in the settings with that
// defined by the text itself
optionsCopy.displayMode = data[i].display;
try {
if (optionsCopy.preProcess) {
math = optionsCopy.preProcess(math);
}
external_katex_default().render(math, span, optionsCopy);
} catch (e) {
if (!(e instanceof (external_katex_default()).ParseError)) {
throw e;
}
optionsCopy.errorCallback("KaTeX auto-render: Failed to parse `" + data[i].data + "` with ", e);
fragment.appendChild(document.createTextNode(data[i].rawData));
continue;
}
fragment.appendChild(span);
}
}
return fragment;
};
var renderElem = function renderElem(elem, optionsCopy) {
for (var i = 0; i < elem.childNodes.length; i++) {
var childNode = elem.childNodes[i];
if (childNode.nodeType === 3) {
// Text node
var frag = renderMathInText(childNode.textContent, optionsCopy);
if (frag) {
i += frag.childNodes.length - 1;
elem.replaceChild(frag, childNode);
}
} else if (childNode.nodeType === 1) {
(function () {
// Element node
var className = ' ' + childNode.className + ' ';
var shouldRender = optionsCopy.ignoredTags.indexOf(childNode.nodeName.toLowerCase()) === -1 && optionsCopy.ignoredClasses.every(function (x) {
return className.indexOf(' ' + x + ' ') === -1;
});
if (shouldRender) {
renderElem(childNode, optionsCopy);
}
})();
} // Otherwise, it's something else, and ignore it.
}
};
var renderMathInElement = function renderMathInElement(elem, options) {
if (!elem) {
throw new Error("No element provided to render");
}
var optionsCopy = {}; // Object.assign(optionsCopy, option)
for (var option in options) {
if (options.hasOwnProperty(option)) {
optionsCopy[option] = options[option];
}
} // default options
optionsCopy.delimiters = optionsCopy.delimiters || [{
left: "$$",
right: "$$",
display: true
}, {
left: "\\(",
right: "\\)",
display: false
}, // LaTeX uses $…$, but it ruins the display of normal `$` in text:
// {left: "$", right: "$", display: false},
// $ must come after $$
// Render AMS environments even if outside $$…$$ delimiters.
{
left: "\\begin{equation}",
right: "\\end{equation}",
display: true
}, {
left: "\\begin{align}",
right: "\\end{align}",
display: true
}, {
left: "\\begin{alignat}",
right: "\\end{alignat}",
display: true
}, {
left: "\\begin{gather}",
right: "\\end{gather}",
display: true
}, {
left: "\\begin{CD}",
right: "\\end{CD}",
display: true
}, {
left: "\\[",
right: "\\]",
display: true
}];
optionsCopy.ignoredTags = optionsCopy.ignoredTags || ["script", "noscript", "style", "textarea", "pre", "code", "option"];
optionsCopy.ignoredClasses = optionsCopy.ignoredClasses || [];
optionsCopy.errorCallback = optionsCopy.errorCallback || console.error; // Enable sharing of global macros defined via `\gdef` between different
// math elements within a single call to `renderMathInElement`.
optionsCopy.macros = optionsCopy.macros || {};
renderElem(elem, optionsCopy);
};
/* harmony default export */ var auto_render = (renderMathInElement);
}();
__webpack_exports__ = __webpack_exports__["default"];
/******/ return __webpack_exports__;
/******/ })()
;
});

View File

@ -0,0 +1 @@
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(require("katex")):"function"==typeof define&&define.amd?define(["katex"],t):"object"==typeof exports?exports.renderMathInElement=t(require("katex")):e.renderMathInElement=t(e.katex)}("undefined"!=typeof self?self:this,(function(e){return function(){"use strict";var t={771:function(t){t.exports=e}},r={};function n(e){var a=r[e];if(void 0!==a)return a.exports;var i=r[e]={exports:{}};return t[e](i,i.exports,n),i.exports}n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,{a:t}),t},n.d=function(e,t){for(var r in t)n.o(t,r)&&!n.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)};var a={};return function(){n.d(a,{default:function(){return s}});var e=n(771),t=n.n(e),r=function(e,t,r){for(var n=r,a=0,i=e.length;n<t.length;){var o=t[n];if(a<=0&&t.slice(n,n+i)===e)return n;"\\"===o?n++:"{"===o?a++:"}"===o&&a--,n++}return-1},i=/^\\begin{/,o=function(e,t){for(var n,a=[],o=new RegExp("("+t.map((function(e){return e.left.replace(/[-/\\^$*+?.()|[\]{}]/g,"\\$&")})).join("|")+")");-1!==(n=e.search(o));){n>0&&(a.push({type:"text",data:e.slice(0,n)}),e=e.slice(n));var l=t.findIndex((function(t){return e.startsWith(t.left)}));if(-1===(n=r(t[l].right,e,t[l].left.length)))break;var d=e.slice(0,n+t[l].right.length),s=i.test(d)?d:e.slice(t[l].left.length,n);a.push({type:"math",data:s,rawData:d,display:t[l].display}),e=e.slice(n+t[l].right.length)}return""!==e&&a.push({type:"text",data:e}),a},l=function(e,r){var n=o(e,r.delimiters);if(1===n.length&&"text"===n[0].type)return null;for(var a=document.createDocumentFragment(),i=0;i<n.length;i++)if("text"===n[i].type)a.appendChild(document.createTextNode(n[i].data));else{var l=document.createElement("span"),d=n[i].data;r.displayMode=n[i].display;try{r.preProcess&&(d=r.preProcess(d)),t().render(d,l,r)}catch(e){if(!(e instanceof t().ParseError))throw e;r.errorCallback("KaTeX auto-render: Failed to parse `"+n[i].data+"` with ",e),a.appendChild(document.createTextNode(n[i].rawData));continue}a.appendChild(l)}return a},d=function e(t,r){for(var n=0;n<t.childNodes.length;n++){var a=t.childNodes[n];if(3===a.nodeType){var i=l(a.textContent,r);i&&(n+=i.childNodes.length-1,t.replaceChild(i,a))}else 1===a.nodeType&&function(){var t=" "+a.className+" ";-1===r.ignoredTags.indexOf(a.nodeName.toLowerCase())&&r.ignoredClasses.every((function(e){return-1===t.indexOf(" "+e+" ")}))&&e(a,r)}()}},s=function(e,t){if(!e)throw new Error("No element provided to render");var r={};for(var n in t)t.hasOwnProperty(n)&&(r[n]=t[n]);r.delimiters=r.delimiters||[{left:"$$",right:"$$",display:!0},{left:"\\(",right:"\\)",display:!1},{left:"\\begin{equation}",right:"\\end{equation}",display:!0},{left:"\\begin{align}",right:"\\end{align}",display:!0},{left:"\\begin{alignat}",right:"\\end{alignat}",display:!0},{left:"\\begin{gather}",right:"\\end{gather}",display:!0},{left:"\\begin{CD}",right:"\\end{CD}",display:!0},{left:"\\[",right:"\\]",display:!0}],r.ignoredTags=r.ignoredTags||["script","noscript","style","textarea","pre","code","option"],r.ignoredClasses=r.ignoredClasses||[],r.errorCallback=r.errorCallback||console.error,r.macros=r.macros||{},d(e,r)}}(),a=a.default}()}));

View File

@ -0,0 +1,222 @@
import katex from '../katex.mjs';
/* eslint no-constant-condition:0 */
var findEndOfMath = function findEndOfMath(delimiter, text, startIndex) {
// Adapted from
// https://github.com/Khan/perseus/blob/master/src/perseus-markdown.jsx
var index = startIndex;
var braceLevel = 0;
var delimLength = delimiter.length;
while (index < text.length) {
var character = text[index];
if (braceLevel <= 0 && text.slice(index, index + delimLength) === delimiter) {
return index;
} else if (character === "\\") {
index++;
} else if (character === "{") {
braceLevel++;
} else if (character === "}") {
braceLevel--;
}
index++;
}
return -1;
};
var escapeRegex = function escapeRegex(string) {
return string.replace(/[-/\\^$*+?.()|[\]{}]/g, "\\$&");
};
var amsRegex = /^\\begin{/;
var splitAtDelimiters = function splitAtDelimiters(text, delimiters) {
var index;
var data = [];
var regexLeft = new RegExp("(" + delimiters.map(x => escapeRegex(x.left)).join("|") + ")");
while (true) {
index = text.search(regexLeft);
if (index === -1) {
break;
}
if (index > 0) {
data.push({
type: "text",
data: text.slice(0, index)
});
text = text.slice(index); // now text starts with delimiter
} // ... so this always succeeds:
var i = delimiters.findIndex(delim => text.startsWith(delim.left));
index = findEndOfMath(delimiters[i].right, text, delimiters[i].left.length);
if (index === -1) {
break;
}
var rawData = text.slice(0, index + delimiters[i].right.length);
var math = amsRegex.test(rawData) ? rawData : text.slice(delimiters[i].left.length, index);
data.push({
type: "math",
data: math,
rawData,
display: delimiters[i].display
});
text = text.slice(index + delimiters[i].right.length);
}
if (text !== "") {
data.push({
type: "text",
data: text
});
}
return data;
};
/* eslint no-console:0 */
/* Note: optionsCopy is mutated by this method. If it is ever exposed in the
* API, we should copy it before mutating.
*/
var renderMathInText = function renderMathInText(text, optionsCopy) {
var data = splitAtDelimiters(text, optionsCopy.delimiters);
if (data.length === 1 && data[0].type === 'text') {
// There is no formula in the text.
// Let's return null which means there is no need to replace
// the current text node with a new one.
return null;
}
var fragment = document.createDocumentFragment();
for (var i = 0; i < data.length; i++) {
if (data[i].type === "text") {
fragment.appendChild(document.createTextNode(data[i].data));
} else {
var span = document.createElement("span");
var math = data[i].data; // Override any display mode defined in the settings with that
// defined by the text itself
optionsCopy.displayMode = data[i].display;
try {
if (optionsCopy.preProcess) {
math = optionsCopy.preProcess(math);
}
katex.render(math, span, optionsCopy);
} catch (e) {
if (!(e instanceof katex.ParseError)) {
throw e;
}
optionsCopy.errorCallback("KaTeX auto-render: Failed to parse `" + data[i].data + "` with ", e);
fragment.appendChild(document.createTextNode(data[i].rawData));
continue;
}
fragment.appendChild(span);
}
}
return fragment;
};
var renderElem = function renderElem(elem, optionsCopy) {
for (var i = 0; i < elem.childNodes.length; i++) {
var childNode = elem.childNodes[i];
if (childNode.nodeType === 3) {
// Text node
var frag = renderMathInText(childNode.textContent, optionsCopy);
if (frag) {
i += frag.childNodes.length - 1;
elem.replaceChild(frag, childNode);
}
} else if (childNode.nodeType === 1) {
(function () {
// Element node
var className = ' ' + childNode.className + ' ';
var shouldRender = optionsCopy.ignoredTags.indexOf(childNode.nodeName.toLowerCase()) === -1 && optionsCopy.ignoredClasses.every(x => className.indexOf(' ' + x + ' ') === -1);
if (shouldRender) {
renderElem(childNode, optionsCopy);
}
})();
} // Otherwise, it's something else, and ignore it.
}
};
var renderMathInElement = function renderMathInElement(elem, options) {
if (!elem) {
throw new Error("No element provided to render");
}
var optionsCopy = {}; // Object.assign(optionsCopy, option)
for (var option in options) {
if (options.hasOwnProperty(option)) {
optionsCopy[option] = options[option];
}
} // default options
optionsCopy.delimiters = optionsCopy.delimiters || [{
left: "$$",
right: "$$",
display: true
}, {
left: "\\(",
right: "\\)",
display: false
}, // LaTeX uses $…$, but it ruins the display of normal `$` in text:
// {left: "$", right: "$", display: false},
// $ must come after $$
// Render AMS environments even if outside $$…$$ delimiters.
{
left: "\\begin{equation}",
right: "\\end{equation}",
display: true
}, {
left: "\\begin{align}",
right: "\\end{align}",
display: true
}, {
left: "\\begin{alignat}",
right: "\\end{alignat}",
display: true
}, {
left: "\\begin{gather}",
right: "\\end{gather}",
display: true
}, {
left: "\\begin{CD}",
right: "\\end{CD}",
display: true
}, {
left: "\\[",
right: "\\]",
display: true
}];
optionsCopy.ignoredTags = optionsCopy.ignoredTags || ["script", "noscript", "style", "textarea", "pre", "code", "option"];
optionsCopy.ignoredClasses = optionsCopy.ignoredClasses || [];
optionsCopy.errorCallback = optionsCopy.errorCallback || console.error; // Enable sharing of global macros defined via `\gdef` between different
// math elements within a single call to `renderMathInElement`.
optionsCopy.macros = optionsCopy.macros || {};
renderElem(elem, optionsCopy);
};
export { renderMathInElement as default };

View File

@ -0,0 +1,14 @@
/* Force selection of entire .katex/.katex-display blocks, so that we can
* copy/paste the entire source code. If you omit this CSS, partial
* selections of a formula will work, but will copy the ugly HTML
* representation instead of the LaTeX source code. (Full selections will
* still produce the LaTeX source code.)
*/
.katex,
.katex-display {
-webkit-user-select: all;
-moz-user-select: all;
-ms-user-select: all;
user-select: all;
}

View File

@ -0,0 +1,116 @@
(function webpackUniversalModuleDefinition(root, factory) {
if(typeof exports === 'object' && typeof module === 'object')
module.exports = factory();
else if(typeof define === 'function' && define.amd)
define([], factory);
else {
var a = factory();
for(var i in a) (typeof exports === 'object' ? exports : root)[i] = a[i];
}
})((typeof self !== 'undefined' ? self : this), function() {
return /******/ (function() { // webpackBootstrap
/******/ "use strict";
var __webpack_exports__ = {};
;// CONCATENATED MODULE: ./contrib/copy-tex/katex2tex.js
// Set these to how you want inline and display math to be delimited.
var defaultCopyDelimiters = {
inline: ['$', '$'],
// alternative: ['\(', '\)']
display: ['$$', '$$'] // alternative: ['\[', '\]']
}; // Replace .katex elements with their TeX source (<annotation> element).
// Modifies fragment in-place. Useful for writing your own 'copy' handler,
// as in copy-tex.js.
var katexReplaceWithTex = function katexReplaceWithTex(fragment, copyDelimiters) {
if (copyDelimiters === void 0) {
copyDelimiters = defaultCopyDelimiters;
}
// Remove .katex-html blocks that are preceded by .katex-mathml blocks
// (which will get replaced below).
var katexHtml = fragment.querySelectorAll('.katex-mathml + .katex-html');
for (var i = 0; i < katexHtml.length; i++) {
var element = katexHtml[i];
if (element.remove) {
element.remove(null);
} else {
element.parentNode.removeChild(element);
}
} // Replace .katex-mathml elements with their annotation (TeX source)
// descendant, with inline delimiters.
var katexMathml = fragment.querySelectorAll('.katex-mathml');
for (var _i = 0; _i < katexMathml.length; _i++) {
var _element = katexMathml[_i];
var texSource = _element.querySelector('annotation');
if (texSource) {
if (_element.replaceWith) {
_element.replaceWith(texSource);
} else {
_element.parentNode.replaceChild(texSource, _element);
}
texSource.innerHTML = copyDelimiters.inline[0] + texSource.innerHTML + copyDelimiters.inline[1];
}
} // Switch display math to display delimiters.
var displays = fragment.querySelectorAll('.katex-display annotation');
for (var _i2 = 0; _i2 < displays.length; _i2++) {
var _element2 = displays[_i2];
_element2.innerHTML = copyDelimiters.display[0] + _element2.innerHTML.substr(copyDelimiters.inline[0].length, _element2.innerHTML.length - copyDelimiters.inline[0].length - copyDelimiters.inline[1].length) + copyDelimiters.display[1];
}
return fragment;
};
/* harmony default export */ var katex2tex = (katexReplaceWithTex);
;// CONCATENATED MODULE: ./contrib/copy-tex/copy-tex.js
// Global copy handler to modify behavior on .katex elements.
document.addEventListener('copy', function (event) {
var selection = window.getSelection();
if (selection.isCollapsed) {
return; // default action OK if selection is empty
}
var fragment = selection.getRangeAt(0).cloneContents();
if (!fragment.querySelector('.katex-mathml')) {
return; // default action OK if no .katex-mathml elements
} // Preserve usual HTML copy/paste behavior.
var html = [];
for (var i = 0; i < fragment.childNodes.length; i++) {
html.push(fragment.childNodes[i].outerHTML);
}
event.clipboardData.setData('text/html', html.join('')); // Rewrite plain-text version.
event.clipboardData.setData('text/plain', katex2tex(fragment).textContent); // Prevent normal copy handling.
event.preventDefault();
});
;// CONCATENATED MODULE: ./contrib/copy-tex/copy-tex.webpack.js
/**
* This is the webpack entry point for KaTeX. As ECMAScript doesn't support
* CSS modules natively, a separate entry point is used.
*/
__webpack_exports__ = __webpack_exports__["default"];
/******/ return __webpack_exports__;
/******/ })()
;
});

1
static/katex/contrib/copy-tex.min.css vendored Normal file
View File

@ -0,0 +1 @@
.katex,.katex-display{-webkit-user-select:all;-moz-user-select:all;-ms-user-select:all;user-select:all}

1
static/katex/contrib/copy-tex.min.js vendored Normal file
View File

@ -0,0 +1 @@
!function(e,t){if("object"==typeof exports&&"object"==typeof module)module.exports=t();else if("function"==typeof define&&define.amd)define([],t);else{var n=t();for(var l in n)("object"==typeof exports?exports:e)[l]=n[l]}}("undefined"!=typeof self?self:this,(function(){return function(){"use strict";var e={},t={inline:["$","$"],display:["$$","$$"]},n=function(e,n){void 0===n&&(n=t);for(var l=e.querySelectorAll(".katex-mathml + .katex-html"),r=0;r<l.length;r++){var i=l[r];i.remove?i.remove(null):i.parentNode.removeChild(i)}for(var o=e.querySelectorAll(".katex-mathml"),a=0;a<o.length;a++){var d=o[a],f=d.querySelector("annotation");f&&(d.replaceWith?d.replaceWith(f):d.parentNode.replaceChild(f,d),f.innerHTML=n.inline[0]+f.innerHTML+n.inline[1])}for(var c=e.querySelectorAll(".katex-display annotation"),s=0;s<c.length;s++){var p=c[s];p.innerHTML=n.display[0]+p.innerHTML.substr(n.inline[0].length,p.innerHTML.length-n.inline[0].length-n.inline[1].length)+n.display[1]}return e};return document.addEventListener("copy",(function(e){var t=window.getSelection();if(!t.isCollapsed){var l=t.getRangeAt(0).cloneContents();if(l.querySelector(".katex-mathml")){for(var r=[],i=0;i<l.childNodes.length;i++)r.push(l.childNodes[i].outerHTML);e.clipboardData.setData("text/html",r.join("")),e.clipboardData.setData("text/plain",n(l).textContent),e.preventDefault()}}})),e=e.default}()}));

View File

@ -0,0 +1,86 @@
// Set these to how you want inline and display math to be delimited.
var defaultCopyDelimiters = {
inline: ['$', '$'],
// alternative: ['\(', '\)']
display: ['$$', '$$'] // alternative: ['\[', '\]']
}; // Replace .katex elements with their TeX source (<annotation> element).
// Modifies fragment in-place. Useful for writing your own 'copy' handler,
// as in copy-tex.js.
var katexReplaceWithTex = function katexReplaceWithTex(fragment, copyDelimiters) {
if (copyDelimiters === void 0) {
copyDelimiters = defaultCopyDelimiters;
}
// Remove .katex-html blocks that are preceded by .katex-mathml blocks
// (which will get replaced below).
var katexHtml = fragment.querySelectorAll('.katex-mathml + .katex-html');
for (var i = 0; i < katexHtml.length; i++) {
var element = katexHtml[i];
if (element.remove) {
element.remove(null);
} else {
element.parentNode.removeChild(element);
}
} // Replace .katex-mathml elements with their annotation (TeX source)
// descendant, with inline delimiters.
var katexMathml = fragment.querySelectorAll('.katex-mathml');
for (var _i = 0; _i < katexMathml.length; _i++) {
var _element = katexMathml[_i];
var texSource = _element.querySelector('annotation');
if (texSource) {
if (_element.replaceWith) {
_element.replaceWith(texSource);
} else {
_element.parentNode.replaceChild(texSource, _element);
}
texSource.innerHTML = copyDelimiters.inline[0] + texSource.innerHTML + copyDelimiters.inline[1];
}
} // Switch display math to display delimiters.
var displays = fragment.querySelectorAll('.katex-display annotation');
for (var _i2 = 0; _i2 < displays.length; _i2++) {
var _element2 = displays[_i2];
_element2.innerHTML = copyDelimiters.display[0] + _element2.innerHTML.substr(copyDelimiters.inline[0].length, _element2.innerHTML.length - copyDelimiters.inline[0].length - copyDelimiters.inline[1].length) + copyDelimiters.display[1];
}
return fragment;
};
document.addEventListener('copy', function (event) {
var selection = window.getSelection();
if (selection.isCollapsed) {
return; // default action OK if selection is empty
}
var fragment = selection.getRangeAt(0).cloneContents();
if (!fragment.querySelector('.katex-mathml')) {
return; // default action OK if no .katex-mathml elements
} // Preserve usual HTML copy/paste behavior.
var html = [];
for (var i = 0; i < fragment.childNodes.length; i++) {
html.push(fragment.childNodes[i].outerHTML);
}
event.clipboardData.setData('text/html', html.join('')); // Rewrite plain-text version.
event.clipboardData.setData('text/plain', katexReplaceWithTex(fragment).textContent); // Prevent normal copy handling.
event.preventDefault();
});

View File

@ -0,0 +1,112 @@
(function webpackUniversalModuleDefinition(root, factory) {
if(typeof exports === 'object' && typeof module === 'object')
module.exports = factory(require("katex"));
else if(typeof define === 'function' && define.amd)
define(["katex"], factory);
else {
var a = typeof exports === 'object' ? factory(require("katex")) : factory(root["katex"]);
for(var i in a) (typeof exports === 'object' ? exports : root)[i] = a[i];
}
})((typeof self !== 'undefined' ? self : this), function(__WEBPACK_EXTERNAL_MODULE__771__) {
return /******/ (function() { // webpackBootstrap
/******/ "use strict";
/******/ var __webpack_modules__ = ({
/***/ 771:
/***/ (function(module) {
module.exports = __WEBPACK_EXTERNAL_MODULE__771__;
/***/ })
/******/ });
/************************************************************************/
/******/ // The module cache
/******/ var __webpack_module_cache__ = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/ // Check if module is in cache
/******/ var cachedModule = __webpack_module_cache__[moduleId];
/******/ if (cachedModule !== undefined) {
/******/ return cachedModule.exports;
/******/ }
/******/ // Create a new module (and put it into the cache)
/******/ var module = __webpack_module_cache__[moduleId] = {
/******/ // no module.id needed
/******/ // no module.loaded needed
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__);
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/************************************************************************/
/******/ /* webpack/runtime/compat get default export */
/******/ !function() {
/******/ // getDefaultExport function for compatibility with non-harmony modules
/******/ __webpack_require__.n = function(module) {
/******/ var getter = module && module.__esModule ?
/******/ function() { return module['default']; } :
/******/ function() { return module; };
/******/ __webpack_require__.d(getter, { a: getter });
/******/ return getter;
/******/ };
/******/ }();
/******/
/******/ /* webpack/runtime/define property getters */
/******/ !function() {
/******/ // define getter functions for harmony exports
/******/ __webpack_require__.d = function(exports, definition) {
/******/ for(var key in definition) {
/******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
/******/ }
/******/ }
/******/ };
/******/ }();
/******/
/******/ /* webpack/runtime/hasOwnProperty shorthand */
/******/ !function() {
/******/ __webpack_require__.o = function(obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); }
/******/ }();
/******/
/************************************************************************/
var __webpack_exports__ = {};
// This entry need to be wrapped in an IIFE because it need to be isolated against other modules in the chunk.
!function() {
/* harmony import */ var katex__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(771);
/* harmony import */ var katex__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(katex__WEBPACK_IMPORTED_MODULE_0__);
var scripts = document.body.getElementsByTagName("script");
scripts = Array.prototype.slice.call(scripts);
scripts.forEach(function (script) {
if (!script.type || !script.type.match(/math\/tex/i)) {
return -1;
}
var display = script.type.match(/mode\s*=\s*display(;|\s|\n|$)/) != null;
var katexElement = document.createElement(display ? "div" : "span");
katexElement.setAttribute("class", display ? "equation" : "inline-equation");
try {
katex__WEBPACK_IMPORTED_MODULE_0___default().render(script.text, katexElement, {
displayMode: display
});
} catch (err) {
//console.error(err); linter doesn't like this
katexElement.textContent = script.text;
}
script.parentNode.replaceChild(katexElement, script);
});
}();
__webpack_exports__ = __webpack_exports__["default"];
/******/ return __webpack_exports__;
/******/ })()
;
});

View File

@ -0,0 +1 @@
!function(e,t){if("object"==typeof exports&&"object"==typeof module)module.exports=t(require("katex"));else if("function"==typeof define&&define.amd)define(["katex"],t);else{var r="object"==typeof exports?t(require("katex")):t(e.katex);for(var n in r)("object"==typeof exports?exports:e)[n]=r[n]}}("undefined"!=typeof self?self:this,(function(e){return function(){"use strict";var t={771:function(t){t.exports=e}},r={};function n(e){var o=r[e];if(void 0!==o)return o.exports;var i=r[e]={exports:{}};return t[e](i,i.exports,n),i.exports}n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,{a:t}),t},n.d=function(e,t){for(var r in t)n.o(t,r)&&!n.o(e,r)&&Object.defineProperty(e,r,{enumerable:!0,get:t[r]})},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)};var o,i,a,u={};return o=n(771),i=n.n(o),a=document.body.getElementsByTagName("script"),(a=Array.prototype.slice.call(a)).forEach((function(e){if(!e.type||!e.type.match(/math\/tex/i))return-1;var t=null!=e.type.match(/mode\s*=\s*display(;|\s|\n|$)/),r=document.createElement(t?"div":"span");r.setAttribute("class",t?"equation":"inline-equation");try{i().render(e.text,r,{displayMode:t})}catch(t){r.textContent=e.text}e.parentNode.replaceChild(r,e)})),u=u.default}()}));

View File

@ -0,0 +1,24 @@
import katex from '../katex.mjs';
var scripts = document.body.getElementsByTagName("script");
scripts = Array.prototype.slice.call(scripts);
scripts.forEach(function (script) {
if (!script.type || !script.type.match(/math\/tex/i)) {
return -1;
}
var display = script.type.match(/mode\s*=\s*display(;|\s|\n|$)/) != null;
var katexElement = document.createElement(display ? "div" : "span");
katexElement.setAttribute("class", display ? "equation" : "inline-equation");
try {
katex.render(script.text, katexElement, {
displayMode: display
});
} catch (err) {
//console.error(err); linter doesn't like this
katexElement.textContent = script.text;
}
script.parentNode.replaceChild(katexElement, script);
});

File diff suppressed because it is too large Load Diff

1
static/katex/contrib/mhchem.min.js vendored Normal file

File diff suppressed because one or more lines are too long

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,875 @@
(function webpackUniversalModuleDefinition(root, factory) {
if(typeof exports === 'object' && typeof module === 'object')
module.exports = factory(require("katex"));
else if(typeof define === 'function' && define.amd)
define(["katex"], factory);
else {
var a = typeof exports === 'object' ? factory(require("katex")) : factory(root["katex"]);
for(var i in a) (typeof exports === 'object' ? exports : root)[i] = a[i];
}
})((typeof self !== 'undefined' ? self : this), function(__WEBPACK_EXTERNAL_MODULE__771__) {
return /******/ (function() { // webpackBootstrap
/******/ "use strict";
/******/ var __webpack_modules__ = ({
/***/ 771:
/***/ (function(module) {
module.exports = __WEBPACK_EXTERNAL_MODULE__771__;
/***/ })
/******/ });
/************************************************************************/
/******/ // The module cache
/******/ var __webpack_module_cache__ = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/ // Check if module is in cache
/******/ var cachedModule = __webpack_module_cache__[moduleId];
/******/ if (cachedModule !== undefined) {
/******/ return cachedModule.exports;
/******/ }
/******/ // Create a new module (and put it into the cache)
/******/ var module = __webpack_module_cache__[moduleId] = {
/******/ // no module.id needed
/******/ // no module.loaded needed
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ __webpack_modules__[moduleId](module, module.exports, __webpack_require__);
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/************************************************************************/
/******/ /* webpack/runtime/compat get default export */
/******/ !function() {
/******/ // getDefaultExport function for compatibility with non-harmony modules
/******/ __webpack_require__.n = function(module) {
/******/ var getter = module && module.__esModule ?
/******/ function() { return module['default']; } :
/******/ function() { return module; };
/******/ __webpack_require__.d(getter, { a: getter });
/******/ return getter;
/******/ };
/******/ }();
/******/
/******/ /* webpack/runtime/define property getters */
/******/ !function() {
/******/ // define getter functions for harmony exports
/******/ __webpack_require__.d = function(exports, definition) {
/******/ for(var key in definition) {
/******/ if(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {
/******/ Object.defineProperty(exports, key, { enumerable: true, get: definition[key] });
/******/ }
/******/ }
/******/ };
/******/ }();
/******/
/******/ /* webpack/runtime/hasOwnProperty shorthand */
/******/ !function() {
/******/ __webpack_require__.o = function(obj, prop) { return Object.prototype.hasOwnProperty.call(obj, prop); }
/******/ }();
/******/
/************************************************************************/
var __webpack_exports__ = {};
// This entry need to be wrapped in an IIFE because it need to be isolated against other modules in the chunk.
!function() {
/* harmony import */ var katex__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(771);
/* harmony import */ var katex__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(katex__WEBPACK_IMPORTED_MODULE_0__);
/**
* renderA11yString returns a readable string.
*
* In some cases the string will have the proper semantic math
* meaning,:
* renderA11yString("\\frac{1}{2}"")
* -> "start fraction, 1, divided by, 2, end fraction"
*
* However, other cases do not:
* renderA11yString("f(x) = x^2")
* -> "f, left parenthesis, x, right parenthesis, equals, x, squared"
*
* The commas in the string aim to increase ease of understanding
* when read by a screenreader.
*/
// NOTE: since we're importing types here these files won't actually be
// included in the build.
// $FlowIgnore: we import the types directly anyways
var stringMap = {
"(": "left parenthesis",
")": "right parenthesis",
"[": "open bracket",
"]": "close bracket",
"\\{": "left brace",
"\\}": "right brace",
"\\lvert": "open vertical bar",
"\\rvert": "close vertical bar",
"|": "vertical bar",
"\\uparrow": "up arrow",
"\\Uparrow": "up arrow",
"\\downarrow": "down arrow",
"\\Downarrow": "down arrow",
"\\updownarrow": "up down arrow",
"\\leftarrow": "left arrow",
"\\Leftarrow": "left arrow",
"\\rightarrow": "right arrow",
"\\Rightarrow": "right arrow",
"\\langle": "open angle",
"\\rangle": "close angle",
"\\lfloor": "open floor",
"\\rfloor": "close floor",
"\\int": "integral",
"\\intop": "integral",
"\\lim": "limit",
"\\ln": "natural log",
"\\log": "log",
"\\sin": "sine",
"\\cos": "cosine",
"\\tan": "tangent",
"\\cot": "cotangent",
"\\sum": "sum",
"/": "slash",
",": "comma",
".": "point",
"-": "negative",
"+": "plus",
"~": "tilde",
":": "colon",
"?": "question mark",
"'": "apostrophe",
"\\%": "percent",
" ": "space",
"\\ ": "space",
"\\$": "dollar sign",
"\\angle": "angle",
"\\degree": "degree",
"\\circ": "circle",
"\\vec": "vector",
"\\triangle": "triangle",
"\\pi": "pi",
"\\prime": "prime",
"\\infty": "infinity",
"\\alpha": "alpha",
"\\beta": "beta",
"\\gamma": "gamma",
"\\omega": "omega",
"\\theta": "theta",
"\\sigma": "sigma",
"\\lambda": "lambda",
"\\tau": "tau",
"\\Delta": "delta",
"\\delta": "delta",
"\\mu": "mu",
"\\rho": "rho",
"\\nabla": "del",
"\\ell": "ell",
"\\ldots": "dots",
// TODO: add entries for all accents
"\\hat": "hat",
"\\acute": "acute"
};
var powerMap = {
"prime": "prime",
"degree": "degrees",
"circle": "degrees",
"2": "squared",
"3": "cubed"
};
var openMap = {
"|": "open vertical bar",
".": ""
};
var closeMap = {
"|": "close vertical bar",
".": ""
};
var binMap = {
"+": "plus",
"-": "minus",
"\\pm": "plus minus",
"\\cdot": "dot",
"*": "times",
"/": "divided by",
"\\times": "times",
"\\div": "divided by",
"\\circ": "circle",
"\\bullet": "bullet"
};
var relMap = {
"=": "equals",
"\\approx": "approximately equals",
"≠": "does not equal",
"\\geq": "is greater than or equal to",
"\\ge": "is greater than or equal to",
"\\leq": "is less than or equal to",
"\\le": "is less than or equal to",
">": "is greater than",
"<": "is less than",
"\\leftarrow": "left arrow",
"\\Leftarrow": "left arrow",
"\\rightarrow": "right arrow",
"\\Rightarrow": "right arrow",
":": "colon"
};
var accentUnderMap = {
"\\underleftarrow": "left arrow",
"\\underrightarrow": "right arrow",
"\\underleftrightarrow": "left-right arrow",
"\\undergroup": "group",
"\\underlinesegment": "line segment",
"\\utilde": "tilde"
};
var buildString = function buildString(str, type, a11yStrings) {
if (!str) {
return;
}
var ret;
if (type === "open") {
ret = str in openMap ? openMap[str] : stringMap[str] || str;
} else if (type === "close") {
ret = str in closeMap ? closeMap[str] : stringMap[str] || str;
} else if (type === "bin") {
ret = binMap[str] || str;
} else if (type === "rel") {
ret = relMap[str] || str;
} else {
ret = stringMap[str] || str;
} // If the text to add is a number and there is already a string
// in the list and the last string is a number then we should
// combine them into a single number
if (/^\d+$/.test(ret) && a11yStrings.length > 0 && // TODO(kevinb): check that the last item in a11yStrings is a string
// I think we might be able to drop the nested arrays, which would make
// this easier to type
// $FlowFixMe
/^\d+$/.test(a11yStrings[a11yStrings.length - 1])) {
a11yStrings[a11yStrings.length - 1] += ret;
} else if (ret) {
a11yStrings.push(ret);
}
};
var buildRegion = function buildRegion(a11yStrings, callback) {
var regionStrings = [];
a11yStrings.push(regionStrings);
callback(regionStrings);
};
var handleObject = function handleObject(tree, a11yStrings, atomType) {
// Everything else is assumed to be an object...
switch (tree.type) {
case "accent":
{
buildRegion(a11yStrings, function (a11yStrings) {
buildA11yStrings(tree.base, a11yStrings, atomType);
a11yStrings.push("with");
buildString(tree.label, "normal", a11yStrings);
a11yStrings.push("on top");
});
break;
}
case "accentUnder":
{
buildRegion(a11yStrings, function (a11yStrings) {
buildA11yStrings(tree.base, a11yStrings, atomType);
a11yStrings.push("with");
buildString(accentUnderMap[tree.label], "normal", a11yStrings);
a11yStrings.push("underneath");
});
break;
}
case "accent-token":
{
// Used internally by accent symbols.
break;
}
case "atom":
{
var text = tree.text;
switch (tree.family) {
case "bin":
{
buildString(text, "bin", a11yStrings);
break;
}
case "close":
{
buildString(text, "close", a11yStrings);
break;
}
// TODO(kevinb): figure out what should be done for inner
case "inner":
{
buildString(tree.text, "inner", a11yStrings);
break;
}
case "open":
{
buildString(text, "open", a11yStrings);
break;
}
case "punct":
{
buildString(text, "punct", a11yStrings);
break;
}
case "rel":
{
buildString(text, "rel", a11yStrings);
break;
}
default:
{
tree.family;
throw new Error("\"" + tree.family + "\" is not a valid atom type");
}
}
break;
}
case "color":
{
var color = tree.color.replace(/katex-/, "");
buildRegion(a11yStrings, function (regionStrings) {
regionStrings.push("start color " + color);
buildA11yStrings(tree.body, regionStrings, atomType);
regionStrings.push("end color " + color);
});
break;
}
case "color-token":
{
// Used by \color, \colorbox, and \fcolorbox but not directly rendered.
// It's a leaf node and has no children so just break.
break;
}
case "delimsizing":
{
if (tree.delim && tree.delim !== ".") {
buildString(tree.delim, "normal", a11yStrings);
}
break;
}
case "genfrac":
{
buildRegion(a11yStrings, function (regionStrings) {
// genfrac can have unbalanced delimiters
var leftDelim = tree.leftDelim,
rightDelim = tree.rightDelim; // NOTE: Not sure if this is a safe assumption
// hasBarLine true -> fraction, false -> binomial
if (tree.hasBarLine) {
regionStrings.push("start fraction");
leftDelim && buildString(leftDelim, "open", regionStrings);
buildA11yStrings(tree.numer, regionStrings, atomType);
regionStrings.push("divided by");
buildA11yStrings(tree.denom, regionStrings, atomType);
rightDelim && buildString(rightDelim, "close", regionStrings);
regionStrings.push("end fraction");
} else {
regionStrings.push("start binomial");
leftDelim && buildString(leftDelim, "open", regionStrings);
buildA11yStrings(tree.numer, regionStrings, atomType);
regionStrings.push("over");
buildA11yStrings(tree.denom, regionStrings, atomType);
rightDelim && buildString(rightDelim, "close", regionStrings);
regionStrings.push("end binomial");
}
});
break;
}
case "hbox":
{
buildA11yStrings(tree.body, a11yStrings, atomType);
break;
}
case "kern":
{
// No op: we don't attempt to present kerning information
// to the screen reader.
break;
}
case "leftright":
{
buildRegion(a11yStrings, function (regionStrings) {
buildString(tree.left, "open", regionStrings);
buildA11yStrings(tree.body, regionStrings, atomType);
buildString(tree.right, "close", regionStrings);
});
break;
}
case "leftright-right":
{
// TODO: double check that this is a no-op
break;
}
case "lap":
{
buildA11yStrings(tree.body, a11yStrings, atomType);
break;
}
case "mathord":
{
buildString(tree.text, "normal", a11yStrings);
break;
}
case "op":
{
var body = tree.body,
name = tree.name;
if (body) {
buildA11yStrings(body, a11yStrings, atomType);
} else if (name) {
buildString(name, "normal", a11yStrings);
}
break;
}
case "op-token":
{
// Used internally by operator symbols.
buildString(tree.text, atomType, a11yStrings);
break;
}
case "ordgroup":
{
buildA11yStrings(tree.body, a11yStrings, atomType);
break;
}
case "overline":
{
buildRegion(a11yStrings, function (a11yStrings) {
a11yStrings.push("start overline");
buildA11yStrings(tree.body, a11yStrings, atomType);
a11yStrings.push("end overline");
});
break;
}
case "phantom":
{
a11yStrings.push("empty space");
break;
}
case "raisebox":
{
buildA11yStrings(tree.body, a11yStrings, atomType);
break;
}
case "rule":
{
a11yStrings.push("rectangle");
break;
}
case "sizing":
{
buildA11yStrings(tree.body, a11yStrings, atomType);
break;
}
case "spacing":
{
a11yStrings.push("space");
break;
}
case "styling":
{
// We ignore the styling and just pass through the contents
buildA11yStrings(tree.body, a11yStrings, atomType);
break;
}
case "sqrt":
{
buildRegion(a11yStrings, function (regionStrings) {
var body = tree.body,
index = tree.index;
if (index) {
var indexString = flatten(buildA11yStrings(index, [], atomType)).join(",");
if (indexString === "3") {
regionStrings.push("cube root of");
buildA11yStrings(body, regionStrings, atomType);
regionStrings.push("end cube root");
return;
}
regionStrings.push("root");
regionStrings.push("start index");
buildA11yStrings(index, regionStrings, atomType);
regionStrings.push("end index");
return;
}
regionStrings.push("square root of");
buildA11yStrings(body, regionStrings, atomType);
regionStrings.push("end square root");
});
break;
}
case "supsub":
{
var base = tree.base,
sub = tree.sub,
sup = tree.sup;
var isLog = false;
if (base) {
buildA11yStrings(base, a11yStrings, atomType);
isLog = base.type === "op" && base.name === "\\log";
}
if (sub) {
var regionName = isLog ? "base" : "subscript";
buildRegion(a11yStrings, function (regionStrings) {
regionStrings.push("start " + regionName);
buildA11yStrings(sub, regionStrings, atomType);
regionStrings.push("end " + regionName);
});
}
if (sup) {
buildRegion(a11yStrings, function (regionStrings) {
var supString = flatten(buildA11yStrings(sup, [], atomType)).join(",");
if (supString in powerMap) {
regionStrings.push(powerMap[supString]);
return;
}
regionStrings.push("start superscript");
buildA11yStrings(sup, regionStrings, atomType);
regionStrings.push("end superscript");
});
}
break;
}
case "text":
{
// TODO: handle other fonts
if (tree.font === "\\textbf") {
buildRegion(a11yStrings, function (regionStrings) {
regionStrings.push("start bold text");
buildA11yStrings(tree.body, regionStrings, atomType);
regionStrings.push("end bold text");
});
break;
}
buildRegion(a11yStrings, function (regionStrings) {
regionStrings.push("start text");
buildA11yStrings(tree.body, regionStrings, atomType);
regionStrings.push("end text");
});
break;
}
case "textord":
{
buildString(tree.text, atomType, a11yStrings);
break;
}
case "smash":
{
buildA11yStrings(tree.body, a11yStrings, atomType);
break;
}
case "enclose":
{
// TODO: create a map for these.
// TODO: differentiate between a body with a single atom, e.g.
// "cancel a" instead of "start cancel, a, end cancel"
if (/cancel/.test(tree.label)) {
buildRegion(a11yStrings, function (regionStrings) {
regionStrings.push("start cancel");
buildA11yStrings(tree.body, regionStrings, atomType);
regionStrings.push("end cancel");
});
break;
} else if (/box/.test(tree.label)) {
buildRegion(a11yStrings, function (regionStrings) {
regionStrings.push("start box");
buildA11yStrings(tree.body, regionStrings, atomType);
regionStrings.push("end box");
});
break;
} else if (/sout/.test(tree.label)) {
buildRegion(a11yStrings, function (regionStrings) {
regionStrings.push("start strikeout");
buildA11yStrings(tree.body, regionStrings, atomType);
regionStrings.push("end strikeout");
});
break;
} else if (/phase/.test(tree.label)) {
buildRegion(a11yStrings, function (regionStrings) {
regionStrings.push("start phase angle");
buildA11yStrings(tree.body, regionStrings, atomType);
regionStrings.push("end phase angle");
});
break;
}
throw new Error("KaTeX-a11y: enclose node with " + tree.label + " not supported yet");
}
case "vcenter":
{
buildA11yStrings(tree.body, a11yStrings, atomType);
break;
}
case "vphantom":
{
throw new Error("KaTeX-a11y: vphantom not implemented yet");
}
case "hphantom":
{
throw new Error("KaTeX-a11y: hphantom not implemented yet");
}
case "operatorname":
{
buildA11yStrings(tree.body, a11yStrings, atomType);
break;
}
case "array":
{
throw new Error("KaTeX-a11y: array not implemented yet");
}
case "raw":
{
throw new Error("KaTeX-a11y: raw not implemented yet");
}
case "size":
{
// Although there are nodes of type "size" in the parse tree, they have
// no semantic meaning and should be ignored.
break;
}
case "url":
{
throw new Error("KaTeX-a11y: url not implemented yet");
}
case "tag":
{
throw new Error("KaTeX-a11y: tag not implemented yet");
}
case "verb":
{
buildString("start verbatim", "normal", a11yStrings);
buildString(tree.body, "normal", a11yStrings);
buildString("end verbatim", "normal", a11yStrings);
break;
}
case "environment":
{
throw new Error("KaTeX-a11y: environment not implemented yet");
}
case "horizBrace":
{
buildString("start " + tree.label.slice(1), "normal", a11yStrings);
buildA11yStrings(tree.base, a11yStrings, atomType);
buildString("end " + tree.label.slice(1), "normal", a11yStrings);
break;
}
case "infix":
{
// All infix nodes are replace with other nodes.
break;
}
case "includegraphics":
{
throw new Error("KaTeX-a11y: includegraphics not implemented yet");
}
case "font":
{
// TODO: callout the start/end of specific fonts
// TODO: map \BBb{N} to "the naturals" or something like that
buildA11yStrings(tree.body, a11yStrings, atomType);
break;
}
case "href":
{
throw new Error("KaTeX-a11y: href not implemented yet");
}
case "cr":
{
// This is used by environments.
throw new Error("KaTeX-a11y: cr not implemented yet");
}
case "underline":
{
buildRegion(a11yStrings, function (a11yStrings) {
a11yStrings.push("start underline");
buildA11yStrings(tree.body, a11yStrings, atomType);
a11yStrings.push("end underline");
});
break;
}
case "xArrow":
{
throw new Error("KaTeX-a11y: xArrow not implemented yet");
}
case "cdlabel":
{
throw new Error("KaTeX-a11y: cdlabel not implemented yet");
}
case "cdlabelparent":
{
throw new Error("KaTeX-a11y: cdlabelparent not implemented yet");
}
case "mclass":
{
// \neq and \ne are macros so we let "htmlmathml" render the mathmal
// side of things and extract the text from that.
var _atomType = tree.mclass.slice(1); // $FlowFixMe: drop the leading "m" from the values in mclass
buildA11yStrings(tree.body, a11yStrings, _atomType);
break;
}
case "mathchoice":
{
// TODO: track which which style we're using, e.g. dispaly, text, etc.
// default to text style if even that may not be the correct style
buildA11yStrings(tree.text, a11yStrings, atomType);
break;
}
case "htmlmathml":
{
buildA11yStrings(tree.mathml, a11yStrings, atomType);
break;
}
case "middle":
{
buildString(tree.delim, atomType, a11yStrings);
break;
}
case "internal":
{
// internal nodes are never included in the parse tree
break;
}
case "html":
{
buildA11yStrings(tree.body, a11yStrings, atomType);
break;
}
default:
tree.type;
throw new Error("KaTeX a11y un-recognized type: " + tree.type);
}
};
var buildA11yStrings = function buildA11yStrings(tree, a11yStrings, atomType) {
if (a11yStrings === void 0) {
a11yStrings = [];
}
if (tree instanceof Array) {
for (var i = 0; i < tree.length; i++) {
buildA11yStrings(tree[i], a11yStrings, atomType);
}
} else {
handleObject(tree, a11yStrings, atomType);
}
return a11yStrings;
};
var flatten = function flatten(array) {
var result = [];
array.forEach(function (item) {
if (item instanceof Array) {
result = result.concat(flatten(item));
} else {
result.push(item);
}
});
return result;
};
var renderA11yString = function renderA11yString(text, settings) {
var tree = katex__WEBPACK_IMPORTED_MODULE_0___default().__parse(text, settings);
var a11yStrings = buildA11yStrings(tree, [], "normal");
return flatten(a11yStrings).join(", ");
};
/* harmony default export */ __webpack_exports__["default"] = (renderA11yString);
}();
__webpack_exports__ = __webpack_exports__["default"];
/******/ return __webpack_exports__;
/******/ })()
;
});

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,794 @@
import katex from '../katex.mjs';
/**
* renderA11yString returns a readable string.
*
* In some cases the string will have the proper semantic math
* meaning,:
* renderA11yString("\\frac{1}{2}"")
* -> "start fraction, 1, divided by, 2, end fraction"
*
* However, other cases do not:
* renderA11yString("f(x) = x^2")
* -> "f, left parenthesis, x, right parenthesis, equals, x, squared"
*
* The commas in the string aim to increase ease of understanding
* when read by a screenreader.
*/
var stringMap = {
"(": "left parenthesis",
")": "right parenthesis",
"[": "open bracket",
"]": "close bracket",
"\\{": "left brace",
"\\}": "right brace",
"\\lvert": "open vertical bar",
"\\rvert": "close vertical bar",
"|": "vertical bar",
"\\uparrow": "up arrow",
"\\Uparrow": "up arrow",
"\\downarrow": "down arrow",
"\\Downarrow": "down arrow",
"\\updownarrow": "up down arrow",
"\\leftarrow": "left arrow",
"\\Leftarrow": "left arrow",
"\\rightarrow": "right arrow",
"\\Rightarrow": "right arrow",
"\\langle": "open angle",
"\\rangle": "close angle",
"\\lfloor": "open floor",
"\\rfloor": "close floor",
"\\int": "integral",
"\\intop": "integral",
"\\lim": "limit",
"\\ln": "natural log",
"\\log": "log",
"\\sin": "sine",
"\\cos": "cosine",
"\\tan": "tangent",
"\\cot": "cotangent",
"\\sum": "sum",
"/": "slash",
",": "comma",
".": "point",
"-": "negative",
"+": "plus",
"~": "tilde",
":": "colon",
"?": "question mark",
"'": "apostrophe",
"\\%": "percent",
" ": "space",
"\\ ": "space",
"\\$": "dollar sign",
"\\angle": "angle",
"\\degree": "degree",
"\\circ": "circle",
"\\vec": "vector",
"\\triangle": "triangle",
"\\pi": "pi",
"\\prime": "prime",
"\\infty": "infinity",
"\\alpha": "alpha",
"\\beta": "beta",
"\\gamma": "gamma",
"\\omega": "omega",
"\\theta": "theta",
"\\sigma": "sigma",
"\\lambda": "lambda",
"\\tau": "tau",
"\\Delta": "delta",
"\\delta": "delta",
"\\mu": "mu",
"\\rho": "rho",
"\\nabla": "del",
"\\ell": "ell",
"\\ldots": "dots",
// TODO: add entries for all accents
"\\hat": "hat",
"\\acute": "acute"
};
var powerMap = {
"prime": "prime",
"degree": "degrees",
"circle": "degrees",
"2": "squared",
"3": "cubed"
};
var openMap = {
"|": "open vertical bar",
".": ""
};
var closeMap = {
"|": "close vertical bar",
".": ""
};
var binMap = {
"+": "plus",
"-": "minus",
"\\pm": "plus minus",
"\\cdot": "dot",
"*": "times",
"/": "divided by",
"\\times": "times",
"\\div": "divided by",
"\\circ": "circle",
"\\bullet": "bullet"
};
var relMap = {
"=": "equals",
"\\approx": "approximately equals",
"≠": "does not equal",
"\\geq": "is greater than or equal to",
"\\ge": "is greater than or equal to",
"\\leq": "is less than or equal to",
"\\le": "is less than or equal to",
">": "is greater than",
"<": "is less than",
"\\leftarrow": "left arrow",
"\\Leftarrow": "left arrow",
"\\rightarrow": "right arrow",
"\\Rightarrow": "right arrow",
":": "colon"
};
var accentUnderMap = {
"\\underleftarrow": "left arrow",
"\\underrightarrow": "right arrow",
"\\underleftrightarrow": "left-right arrow",
"\\undergroup": "group",
"\\underlinesegment": "line segment",
"\\utilde": "tilde"
};
var buildString = (str, type, a11yStrings) => {
if (!str) {
return;
}
var ret;
if (type === "open") {
ret = str in openMap ? openMap[str] : stringMap[str] || str;
} else if (type === "close") {
ret = str in closeMap ? closeMap[str] : stringMap[str] || str;
} else if (type === "bin") {
ret = binMap[str] || str;
} else if (type === "rel") {
ret = relMap[str] || str;
} else {
ret = stringMap[str] || str;
} // If the text to add is a number and there is already a string
// in the list and the last string is a number then we should
// combine them into a single number
if (/^\d+$/.test(ret) && a11yStrings.length > 0 && // TODO(kevinb): check that the last item in a11yStrings is a string
// I think we might be able to drop the nested arrays, which would make
// this easier to type
// $FlowFixMe
/^\d+$/.test(a11yStrings[a11yStrings.length - 1])) {
a11yStrings[a11yStrings.length - 1] += ret;
} else if (ret) {
a11yStrings.push(ret);
}
};
var buildRegion = (a11yStrings, callback) => {
var regionStrings = [];
a11yStrings.push(regionStrings);
callback(regionStrings);
};
var handleObject = (tree, a11yStrings, atomType) => {
// Everything else is assumed to be an object...
switch (tree.type) {
case "accent":
{
buildRegion(a11yStrings, a11yStrings => {
buildA11yStrings(tree.base, a11yStrings, atomType);
a11yStrings.push("with");
buildString(tree.label, "normal", a11yStrings);
a11yStrings.push("on top");
});
break;
}
case "accentUnder":
{
buildRegion(a11yStrings, a11yStrings => {
buildA11yStrings(tree.base, a11yStrings, atomType);
a11yStrings.push("with");
buildString(accentUnderMap[tree.label], "normal", a11yStrings);
a11yStrings.push("underneath");
});
break;
}
case "accent-token":
{
// Used internally by accent symbols.
break;
}
case "atom":
{
var {
text
} = tree;
switch (tree.family) {
case "bin":
{
buildString(text, "bin", a11yStrings);
break;
}
case "close":
{
buildString(text, "close", a11yStrings);
break;
}
// TODO(kevinb): figure out what should be done for inner
case "inner":
{
buildString(tree.text, "inner", a11yStrings);
break;
}
case "open":
{
buildString(text, "open", a11yStrings);
break;
}
case "punct":
{
buildString(text, "punct", a11yStrings);
break;
}
case "rel":
{
buildString(text, "rel", a11yStrings);
break;
}
default:
{
tree.family;
throw new Error("\"" + tree.family + "\" is not a valid atom type");
}
}
break;
}
case "color":
{
var color = tree.color.replace(/katex-/, "");
buildRegion(a11yStrings, regionStrings => {
regionStrings.push("start color " + color);
buildA11yStrings(tree.body, regionStrings, atomType);
regionStrings.push("end color " + color);
});
break;
}
case "color-token":
{
// Used by \color, \colorbox, and \fcolorbox but not directly rendered.
// It's a leaf node and has no children so just break.
break;
}
case "delimsizing":
{
if (tree.delim && tree.delim !== ".") {
buildString(tree.delim, "normal", a11yStrings);
}
break;
}
case "genfrac":
{
buildRegion(a11yStrings, regionStrings => {
// genfrac can have unbalanced delimiters
var {
leftDelim,
rightDelim
} = tree; // NOTE: Not sure if this is a safe assumption
// hasBarLine true -> fraction, false -> binomial
if (tree.hasBarLine) {
regionStrings.push("start fraction");
leftDelim && buildString(leftDelim, "open", regionStrings);
buildA11yStrings(tree.numer, regionStrings, atomType);
regionStrings.push("divided by");
buildA11yStrings(tree.denom, regionStrings, atomType);
rightDelim && buildString(rightDelim, "close", regionStrings);
regionStrings.push("end fraction");
} else {
regionStrings.push("start binomial");
leftDelim && buildString(leftDelim, "open", regionStrings);
buildA11yStrings(tree.numer, regionStrings, atomType);
regionStrings.push("over");
buildA11yStrings(tree.denom, regionStrings, atomType);
rightDelim && buildString(rightDelim, "close", regionStrings);
regionStrings.push("end binomial");
}
});
break;
}
case "hbox":
{
buildA11yStrings(tree.body, a11yStrings, atomType);
break;
}
case "kern":
{
// No op: we don't attempt to present kerning information
// to the screen reader.
break;
}
case "leftright":
{
buildRegion(a11yStrings, regionStrings => {
buildString(tree.left, "open", regionStrings);
buildA11yStrings(tree.body, regionStrings, atomType);
buildString(tree.right, "close", regionStrings);
});
break;
}
case "leftright-right":
{
// TODO: double check that this is a no-op
break;
}
case "lap":
{
buildA11yStrings(tree.body, a11yStrings, atomType);
break;
}
case "mathord":
{
buildString(tree.text, "normal", a11yStrings);
break;
}
case "op":
{
var {
body,
name
} = tree;
if (body) {
buildA11yStrings(body, a11yStrings, atomType);
} else if (name) {
buildString(name, "normal", a11yStrings);
}
break;
}
case "op-token":
{
// Used internally by operator symbols.
buildString(tree.text, atomType, a11yStrings);
break;
}
case "ordgroup":
{
buildA11yStrings(tree.body, a11yStrings, atomType);
break;
}
case "overline":
{
buildRegion(a11yStrings, function (a11yStrings) {
a11yStrings.push("start overline");
buildA11yStrings(tree.body, a11yStrings, atomType);
a11yStrings.push("end overline");
});
break;
}
case "phantom":
{
a11yStrings.push("empty space");
break;
}
case "raisebox":
{
buildA11yStrings(tree.body, a11yStrings, atomType);
break;
}
case "rule":
{
a11yStrings.push("rectangle");
break;
}
case "sizing":
{
buildA11yStrings(tree.body, a11yStrings, atomType);
break;
}
case "spacing":
{
a11yStrings.push("space");
break;
}
case "styling":
{
// We ignore the styling and just pass through the contents
buildA11yStrings(tree.body, a11yStrings, atomType);
break;
}
case "sqrt":
{
buildRegion(a11yStrings, regionStrings => {
var {
body,
index
} = tree;
if (index) {
var indexString = flatten(buildA11yStrings(index, [], atomType)).join(",");
if (indexString === "3") {
regionStrings.push("cube root of");
buildA11yStrings(body, regionStrings, atomType);
regionStrings.push("end cube root");
return;
}
regionStrings.push("root");
regionStrings.push("start index");
buildA11yStrings(index, regionStrings, atomType);
regionStrings.push("end index");
return;
}
regionStrings.push("square root of");
buildA11yStrings(body, regionStrings, atomType);
regionStrings.push("end square root");
});
break;
}
case "supsub":
{
var {
base,
sub,
sup
} = tree;
var isLog = false;
if (base) {
buildA11yStrings(base, a11yStrings, atomType);
isLog = base.type === "op" && base.name === "\\log";
}
if (sub) {
var regionName = isLog ? "base" : "subscript";
buildRegion(a11yStrings, function (regionStrings) {
regionStrings.push("start " + regionName);
buildA11yStrings(sub, regionStrings, atomType);
regionStrings.push("end " + regionName);
});
}
if (sup) {
buildRegion(a11yStrings, function (regionStrings) {
var supString = flatten(buildA11yStrings(sup, [], atomType)).join(",");
if (supString in powerMap) {
regionStrings.push(powerMap[supString]);
return;
}
regionStrings.push("start superscript");
buildA11yStrings(sup, regionStrings, atomType);
regionStrings.push("end superscript");
});
}
break;
}
case "text":
{
// TODO: handle other fonts
if (tree.font === "\\textbf") {
buildRegion(a11yStrings, function (regionStrings) {
regionStrings.push("start bold text");
buildA11yStrings(tree.body, regionStrings, atomType);
regionStrings.push("end bold text");
});
break;
}
buildRegion(a11yStrings, function (regionStrings) {
regionStrings.push("start text");
buildA11yStrings(tree.body, regionStrings, atomType);
regionStrings.push("end text");
});
break;
}
case "textord":
{
buildString(tree.text, atomType, a11yStrings);
break;
}
case "smash":
{
buildA11yStrings(tree.body, a11yStrings, atomType);
break;
}
case "enclose":
{
// TODO: create a map for these.
// TODO: differentiate between a body with a single atom, e.g.
// "cancel a" instead of "start cancel, a, end cancel"
if (/cancel/.test(tree.label)) {
buildRegion(a11yStrings, function (regionStrings) {
regionStrings.push("start cancel");
buildA11yStrings(tree.body, regionStrings, atomType);
regionStrings.push("end cancel");
});
break;
} else if (/box/.test(tree.label)) {
buildRegion(a11yStrings, function (regionStrings) {
regionStrings.push("start box");
buildA11yStrings(tree.body, regionStrings, atomType);
regionStrings.push("end box");
});
break;
} else if (/sout/.test(tree.label)) {
buildRegion(a11yStrings, function (regionStrings) {
regionStrings.push("start strikeout");
buildA11yStrings(tree.body, regionStrings, atomType);
regionStrings.push("end strikeout");
});
break;
} else if (/phase/.test(tree.label)) {
buildRegion(a11yStrings, function (regionStrings) {
regionStrings.push("start phase angle");
buildA11yStrings(tree.body, regionStrings, atomType);
regionStrings.push("end phase angle");
});
break;
}
throw new Error("KaTeX-a11y: enclose node with " + tree.label + " not supported yet");
}
case "vcenter":
{
buildA11yStrings(tree.body, a11yStrings, atomType);
break;
}
case "vphantom":
{
throw new Error("KaTeX-a11y: vphantom not implemented yet");
}
case "hphantom":
{
throw new Error("KaTeX-a11y: hphantom not implemented yet");
}
case "operatorname":
{
buildA11yStrings(tree.body, a11yStrings, atomType);
break;
}
case "array":
{
throw new Error("KaTeX-a11y: array not implemented yet");
}
case "raw":
{
throw new Error("KaTeX-a11y: raw not implemented yet");
}
case "size":
{
// Although there are nodes of type "size" in the parse tree, they have
// no semantic meaning and should be ignored.
break;
}
case "url":
{
throw new Error("KaTeX-a11y: url not implemented yet");
}
case "tag":
{
throw new Error("KaTeX-a11y: tag not implemented yet");
}
case "verb":
{
buildString("start verbatim", "normal", a11yStrings);
buildString(tree.body, "normal", a11yStrings);
buildString("end verbatim", "normal", a11yStrings);
break;
}
case "environment":
{
throw new Error("KaTeX-a11y: environment not implemented yet");
}
case "horizBrace":
{
buildString("start " + tree.label.slice(1), "normal", a11yStrings);
buildA11yStrings(tree.base, a11yStrings, atomType);
buildString("end " + tree.label.slice(1), "normal", a11yStrings);
break;
}
case "infix":
{
// All infix nodes are replace with other nodes.
break;
}
case "includegraphics":
{
throw new Error("KaTeX-a11y: includegraphics not implemented yet");
}
case "font":
{
// TODO: callout the start/end of specific fonts
// TODO: map \BBb{N} to "the naturals" or something like that
buildA11yStrings(tree.body, a11yStrings, atomType);
break;
}
case "href":
{
throw new Error("KaTeX-a11y: href not implemented yet");
}
case "cr":
{
// This is used by environments.
throw new Error("KaTeX-a11y: cr not implemented yet");
}
case "underline":
{
buildRegion(a11yStrings, function (a11yStrings) {
a11yStrings.push("start underline");
buildA11yStrings(tree.body, a11yStrings, atomType);
a11yStrings.push("end underline");
});
break;
}
case "xArrow":
{
throw new Error("KaTeX-a11y: xArrow not implemented yet");
}
case "cdlabel":
{
throw new Error("KaTeX-a11y: cdlabel not implemented yet");
}
case "cdlabelparent":
{
throw new Error("KaTeX-a11y: cdlabelparent not implemented yet");
}
case "mclass":
{
// \neq and \ne are macros so we let "htmlmathml" render the mathmal
// side of things and extract the text from that.
var _atomType = tree.mclass.slice(1); // $FlowFixMe: drop the leading "m" from the values in mclass
buildA11yStrings(tree.body, a11yStrings, _atomType);
break;
}
case "mathchoice":
{
// TODO: track which which style we're using, e.g. dispaly, text, etc.
// default to text style if even that may not be the correct style
buildA11yStrings(tree.text, a11yStrings, atomType);
break;
}
case "htmlmathml":
{
buildA11yStrings(tree.mathml, a11yStrings, atomType);
break;
}
case "middle":
{
buildString(tree.delim, atomType, a11yStrings);
break;
}
case "internal":
{
// internal nodes are never included in the parse tree
break;
}
case "html":
{
buildA11yStrings(tree.body, a11yStrings, atomType);
break;
}
default:
tree.type;
throw new Error("KaTeX a11y un-recognized type: " + tree.type);
}
};
var buildA11yStrings = function buildA11yStrings(tree, a11yStrings, atomType) {
if (a11yStrings === void 0) {
a11yStrings = [];
}
if (tree instanceof Array) {
for (var i = 0; i < tree.length; i++) {
buildA11yStrings(tree[i], a11yStrings, atomType);
}
} else {
handleObject(tree, a11yStrings, atomType);
}
return a11yStrings;
};
var flatten = function flatten(array) {
var result = [];
array.forEach(function (item) {
if (item instanceof Array) {
result = result.concat(flatten(item));
} else {
result.push(item);
}
});
return result;
};
var renderA11yString = function renderA11yString(text, settings) {
var tree = katex.__parse(text, settings);
var a11yStrings = buildA11yStrings(tree, [], "normal");
return flatten(a11yStrings).join(", ");
};
export { renderA11yString as default };

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More