Compare commits
2 commits
d38c8faa30
...
41ace4dad8
Author | SHA1 | Date | |
---|---|---|---|
41ace4dad8 | |||
0a6b3f0128 |
20
config.toml
|
@ -38,10 +38,10 @@ styles = [
|
|||
]
|
||||
|
||||
bundled_fonts = false
|
||||
issues_url = "https://forgejo.petau.net/aron/awebsite/issues"
|
||||
source_url = "https://forgejo.petau.net/aron/awebsite"
|
||||
issues_url = "https://forgejo.petau.net/aron/studio-umzu/issues"
|
||||
source_url = "https://forgejo.petau.net/aron/studio-umzu"
|
||||
default_theme = "light"
|
||||
accent_color = "#b12633"
|
||||
accent_color = "#ff0000"
|
||||
accent_color_dark = "#c54854"
|
||||
toc = true
|
||||
toc_sidebar = true
|
||||
|
@ -61,20 +61,16 @@ show_feed = true
|
|||
show_theme_switcher = true
|
||||
show_repo = true
|
||||
links = [
|
||||
{ url = "@/_index.md", name = "Projects" },
|
||||
{ url = "https://friedrichwebergoizel.com", name = "Friedrich", external = true },
|
||||
{ url = "https://aron.petau.net", name = "Aron", external = true },
|
||||
]
|
||||
|
||||
|
||||
|
||||
[extra.footer]
|
||||
links = [
|
||||
{ url = "@/_index.md", name = "Projects" },
|
||||
|
||||
]
|
||||
|
||||
socials = [
|
||||
{ url = "https://github.com/arontaupe", name = "GitHub", icon = "%3Csvg role='img' viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Ctitle%3EGitHub%3C/title%3E%3Cpath d='M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12'/%3E%3C/svg%3E" },
|
||||
{ url = "https://www.printables.com/@arontaupe", name = "Printables", icon = "%3Csvg%20role%3D%22img%22%20viewBox%3D%220%200%2024%2024%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Ctitle%3EPrintables%3C%2Ftitle%3E%3Cpath%20d%3D%22M3.678%204.8%2012%209.6v9.6l8.322-4.8V4.8L12%200ZM12%2019.2l-8.322-4.8V24Z%22%2F%3E%3C%2Fsvg%3E" },
|
||||
{ url = "https://www.etsy.com/de-en/shop/reprintedservices", name = "Etsy", icon = "%3Csvg%20role%3D%22img%22%20viewBox%3D%220%200%2024%2024%22%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F2000%2Fsvg%22%3E%3Ctitle%3EEtsy%3C%2Ftitle%3E%3Cpath%20d%3D%22M8.559%202.445c0-.325.033-.52.59-.52h7.465c1.3%200%202.02%201.11%202.54%203.193l.42%201.666h1.27c.23-4.728.43-6.784.43-6.784s-3.196.36-5.09.36H6.635L1.521.196v1.37l1.725.326c1.21.24%201.5.496%201.6%201.606%200%200%20.11%203.27.11%208.64%200%205.385-.09%208.61-.09%208.61%200%20.973-.39%201.333-1.59%201.573l-1.722.33V24l5.13-.165h8.55c1.935%200%206.39.165%206.39.165.105-1.17.75-6.48.855-7.064h-1.2l-1.284%202.91c-1.005%202.28-2.476%202.445-4.11%202.445h-4.906c-1.63%200-2.415-.64-2.415-2.05V12.8s3.62%200%204.79.096c.912.064%201.463.325%201.76%201.598l.39%201.695h1.41l-.09-4.278.192-4.305h-1.391l-.45%201.89c-.283%201.244-.48%201.47-1.754%201.6-1.666.17-4.815.14-4.815.14V2.45h-.05z%22%2F%3E%3C%2Fsvg%3E" },
|
||||
{ url = "https://mastodon.online/@reprintedAron", name = "Mastodon", icon = "%3Csvg role='img' viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Ctitle%3EMastodon%3C/title%3E%3Cpath d='M23.268 5.313c-.35-2.578-2.617-4.61-5.304-5.004C17.51.242 15.792 0 11.813 0h-.03c-3.98 0-4.835.242-5.288.309C3.882.692 1.496 2.518.917 5.127.64 6.412.61 7.837.661 9.143c.074 1.874.088 3.745.26 5.611.118 1.24.325 2.47.62 3.68.55 2.237 2.777 4.098 4.96 4.857 2.336.792 4.849.923 7.256.38.265-.061.527-.132.786-.213.585-.184 1.27-.39 1.774-.753a.057.057 0 0 0 .023-.043v-1.809a.052.052 0 0 0-.02-.041.053.053 0 0 0-.046-.01 20.282 20.282 0 0 1-4.709.545c-2.73 0-3.463-1.284-3.674-1.818a5.593 5.593 0 0 1-.319-1.433.053.053 0 0 1 .066-.054c1.517.363 3.072.546 4.632.546.376 0 .75 0 1.125-.01 1.57-.044 3.224-.124 4.768-.422.038-.008.077-.015.11-.024 2.435-.464 4.753-1.92 4.989-5.604.008-.145.03-1.52.03-1.67.002-.512.167-3.63-.024-5.545zm-3.748 9.195h-2.561V8.29c0-1.309-.55-1.976-1.67-1.976-1.23 0-1.846.79-1.846 2.35v3.403h-2.546V8.663c0-1.56-.617-2.35-1.848-2.35-1.112 0-1.668.668-1.67 1.977v6.218H4.822V8.102c0-1.31.337-2.35 1.011-3.12.696-.77 1.608-1.164 2.74-1.164 1.311 0 2.302.5 2.962 1.498l.638 1.06.638-1.06c.66-.999 1.65-1.498 2.96-1.498 1.13 0 2.043.395 2.74 1.164.675.77 1.012 1.81 1.012 3.12z'/%3E%3C/svg%3E" },
|
||||
{ url = "mailto:aron@petau.net,f.goizel@yahoo.com?subject=Studio%20UM%3CZU", name = "Email", icon = "%3Csvg role='img' viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'%3E%3Ctitle%3EEmail%3C/title%3E%3Cpath d='M1.5 4.5h21a1.5 1.5 0 0 1 1.5 1.5v12a1.5 1.5 0 0 1-1.5 1.5h-21A1.5 1.5 0 0 1 0 18V6a1.5 1.5 0 0 1 1.5-1.5zm10.5 7.125L2.25 6.75v.375L12 12.75l9.75-5.625V6.75l-9.75 4.875z'/%3E%3C/svg%3E" }
|
||||
]
|
||||
show_copyright = true
|
||||
show_powered_by = false
|
||||
|
|
|
@ -22,9 +22,11 @@ Die hier bereitgestellten Informationen können sich noch ändern.
|
|||
|
||||
## Euer Kreativ-Workshop-Team
|
||||
|
||||
Wir sind Aron Petau und Friedrich Weber Goizel — Maker, Pädagogen und leidenschaftliche Tüftler. Wir entwickeln und veranstalten Workshops in Berlin.
|
||||
Wir sind Aron Petau und Friedrich Weber Goizel — Maker, Pädagogen und leidenschaftliche Tüftler.
|
||||
Wir entwickeln und veranstalten Workshops in Berlin.
|
||||
|
||||
Wir bringen die Welt des Machens in Bibliotheken, Schulen und Jugendzentren. Unsere Workshops sind praxisnah und darauf ausgelegt, Kreativität, Neugier und technische Fähigkeiten zu fördern.
|
||||
Wir bringen die Welt des Machens in Bibliotheken, Schulen und Jugendzentren.
|
||||
Unsere Workshops sind praxisnah und darauf ausgelegt, Kreativität, Neugier und technische Fähigkeiten zu fördern.
|
||||
|
||||
Egal, ob ihr schon einen Makerspace mit 3D-Druckern, Lasercuttern oder Plottern habt oder ganz am Anfang steht — wir passen uns an.
|
||||
Wir bieten sowohl mobile Vorführungen und Einführungsveranstaltungen als auch vertiefende Workshops, die auf eurer bestehenden Ausstattung aufbauen.
|
||||
|
@ -46,23 +48,10 @@ Ihr könnt uns für einmalige Veranstaltungen oder laufende Programme kontaktier
|
|||
Wir freuen uns, von euch zu hören!
|
||||
Für Anfragen, Buchungen oder um über einen individuellen Workshop zu sprechen, schreibt uns:
|
||||
|
||||
[aron@petau.net + f.goizel@yahoo.com](mailto:aron@petau.net,f.goizel@yahoo.com?subject=[Workshop])
|
||||
[aron@petau.net + f.goizel@yahoo.com]("mailto:aron@petau.net,f.goizel@yahoo.com?subject=Studio%20UM%3CZU")
|
||||
|
||||
---
|
||||
|
||||
### Referenzen & Erfahrung
|
||||
|
||||
Wir haben Workshops durchgeführt und zusammengearbeitet mit:
|
||||
|
||||
- [Junge Tüftler*innen, Berlin](https://junge-tueftler.de)
|
||||
- [Futurium, Berlin](https://futurium.de)
|
||||
- [Gabriele von Bülow Gymnasium, Berlin](https://www.gvb-berlin.de)
|
||||
- [studio einszwovier](https://www.gvb-berlin.de/unterricht-plus/arbeitsgemeinschaften/maker-space-studio-einszwovier/)
|
||||
- [inküle](https://inkuele.de), Innovationen für die künstlerische Lehre an der UdK
|
||||
- Unterstützt vom Masterprogramm [*New Practice in Design and Technology*](https://www.newpractice.net)
|
||||
- [Friedrich Weber @ New Practice](https://www.newpractice.net/author/friedrich-weber-goizel)
|
||||
- [Aron Petau @ New Practice](https://www.newpractice.net/author/aron-petau)
|
||||
- [Stadtteilbibliothek Karow](https://www.berlin.de/stadtbibliothek-pankow/bibliotheken/stadtteilbibliothek-karow/)
|
||||
|
||||
## Unsere Profile
|
||||
|
||||
|
@ -76,6 +65,11 @@ Wir haben Workshops durchgeführt und zusammengearbeitet mit:
|
|||
|
||||
Aron hat einen Hintergrund in Kognitionswissenschaften, KI und Mediendidaktik.
|
||||
Er liebt knifflige Software-Probleme und denkt gerne über Plastik als Werkstoff jenseits des Druckers nach.
|
||||
Er hat bereits im Grundstudium im Rahmen des Forschungsprojektes [UOS.DLL – Digitales Lernen Leben](https://lehrportal.uni-osnabrueck.de/uosdll/) Makerspaces mit konzipiert und aufgebaut.
|
||||
Auch im künstlerischen Master, [Design and Computation](https://www.newpractice.net/study) beschäftigte er sich viel mit Technikdidaktik und technischen Zukünften.
|
||||
Besonders im Forschungsprogramm [InKüLe](https://inkuele.de), Innovationen für die künstlerische Lehre an der UdK, konnte er viel Erfahrung mit neuen Lehr- und Lernformen sammeln, von Eventbetreuung durch eigene Livestreaminglösungen hin zur Konzeption und Durchführung eigener Workshops zu KI und Virtuellen Realitäten.
|
||||
|
||||
In der Zusammenarbeit im [studio einszwovier](https://www.gvb-berlin.de/unterricht-plus/arbeitsgemeinschaften/maker-space-studio-einszwovier/) mit Friedrich konnte Aron auch seine Masterarbeit zu Designpraxis als peer-learning Format im schulischen Unterricht erproben.
|
||||
|
||||
Hier gibt’s eine ausführliche [Bio](/pages/cv):
|
||||
|
||||
|
@ -87,25 +81,19 @@ Hier gibt’s eine ausführliche [Bio](/pages/cv):
|
|||
|
||||
</aside>
|
||||
|
||||
#### Ausbildung:
|
||||
Friedrich Weber Goizel studierte zunächst Freie Kunst an der [UdK Berlin](https://www.udk-berlin.de/).
|
||||
Später kamen ein Studium der [Humanoiden Robotik](https://www.bht-berlin.de/b-hrob) (BHT) und [Design & Computation](https://www.newpractice.net/study) dazu.
|
||||
|
||||
2014–2015 Studium der Freien Kunst, Hochschule der Künste Braunschweig, Skulptur
|
||||
2022 war er Stipendiat der Kulturstiftung im Programm *„dive in. Programm für digitale Interaktionen“*, in dem der Einsatz von Robotik in öffentlichen Bibliotheken untersucht wurde.
|
||||
Seitdem gibt er selbständig Workshops im Bereich „Making“ an verschiedenen Bibliotheken Berlins.
|
||||
|
||||
2015–2019 Studium der Freien Kunst, Universität der Künste Berlin, Konzept und Neue Medien
|
||||
Als Workshopleiter ist er ebenfalls für die [Jungen Tüftler*innen, Berlin](https://junge-tueftler.de) an diversen Orten wie Stadtteilbibliotheken, Makerspaces oder dem Futurium tätig.
|
||||
Neben der Leitung des Makerspaces [studio einszwovier](https://www.gvb-berlin.de/unterricht-plus/arbeitsgemeinschaften/maker-space-studio-einszwovier/) an einem Berliner Gymnasium, gemeinsam mit Aron, arbeitet Friedrich zudem als Konzept- und Medienkünstler.
|
||||
|
||||
2019 Master of Fine Arts
|
||||
Besonders wichtig ist es ihm, Begeisterung für Technik zu wecken, einen niederschwelligen Einstieg zu geben, gemeinsam Neues auszuprobieren und eine Lernumgebung zu gestalten, in der auf spielerische Weise ein kreativer Zugang zu Technik entsteht.
|
||||
|
||||
2018–2021 Studium humanoide Robotik, Berliner Hochschule für Technik
|
||||
|
||||
2022 Studium Design & Computation, Technische Universität Berlin & Universität der Künste Berlin
|
||||
|
||||
#### Beruf:
|
||||
|
||||
2019–2021 Besucherservice im Futurium Berlin
|
||||
|
||||
2021–2022 Besucherservice und Ausstellungsaufsicht im GID Berlin (Futurium)
|
||||
|
||||
2022 Künstlerisches Forschungsstipendium „KuRoBi4all“ (Kunst, Robotik, Bibliothek für alle); Hochschule für Wirtschaft und Recht Berlin, Stadtbibliotheken Pankow Berlin, Artspring Berlin
|
||||
Finde [hier](https://friedrichwebergoizel.com) mehr über Friedrich heraus.
|
||||
|
||||
---
|
||||
|
||||
|
|
|
@ -48,23 +48,10 @@ You can contact us for one-time events or ongoing programs.
|
|||
We’d love to hear from you!
|
||||
For inquiries, bookings, or to discuss a custom workshop, reach out to us via email at:
|
||||
|
||||
[aron@petau.net + f.goizel@yahoo.com](mailto:aron@petau.net,f.goizel@yahoo.com?subject=[Workshop])
|
||||
[aron@petau.net + f.goizel@yahoo.com]("mailto:aron@petau.net,f.goizel@yahoo.com?subject=Studio%20UM%3CZU")
|
||||
|
||||
---
|
||||
|
||||
### References & Experience
|
||||
|
||||
We’ve run workshops and collaborated with:
|
||||
|
||||
- [Junge Tüftler*innen, Berlin](https://junge-tueftler.de)
|
||||
- [Futurium, Berlin](https://futurium.de)
|
||||
- [Gabriele von Bülow Gymnasium, Berlin](https://www.gvb-berlin.de)
|
||||
- [studio einszwovier](https://www.gvb-berlin.de/unterricht-plus/arbeitsgemeinschaften/maker-space-studio-einszwovier/)
|
||||
- [inküle](https://inkuele.de), Innovationen für die künstlerische Lehre an der UdK
|
||||
- Backed by the [*New Practice in Design and Technology*](https://www.newpractice.net) master’s program
|
||||
- [Friedrich Weber @ New Practice](https://www.newpractice.net/author/friedrich-weber-goizel)
|
||||
- [Aron Petau @ New Practice](https://www.newpractice.net/author/aron-petau)
|
||||
- [Stadtteilbibliothek Karow](https://www.berlin.de/stadtbibliothek-pankow/bibliotheken/stadtteilbibliothek-karow/)
|
||||
|
||||
|
||||
## Our Profiles
|
||||
|
@ -77,10 +64,18 @@ We’ve run workshops and collaborated with:
|
|||
|
||||
</aside>
|
||||
|
||||
Aron has a background in Cognitive sciences, AI and Media Didactics.
|
||||
He loves tricky software problems and likes to think of plastics as a material for making beyond the printer.
|
||||
Aron has a background in Cognitive Science, AI, and Media Didactics.
|
||||
He enjoys tackling tricky software problems and thinking about plastic as a material beyond the 3D printer.
|
||||
|
||||
Read up a full [bio](/pages/cv) here:
|
||||
Already during his undergraduate studies, as part of the research project [UOS.DLL – Digital Learning Living](https://lehrportal.uni-osnabrueck.de/uosdll/), he helped conceptualize and set up makerspaces.
|
||||
In his artistic Master’s program, [Design and Computation](https://www.newpractice.net/study), he also focused heavily on technology didactics and technological futures.
|
||||
|
||||
Within the research program [InKüLe](https://inkuele.de) (*Innovations for Artistic Teaching* at UdK), he gained extensive experience with new forms of teaching and learning — from event support through his own livestreaming solutions to designing and running workshops on AI and Virtual Realities.
|
||||
|
||||
Through his collaboration with Friedrich at [studio einszwovier](https://www.gvb-berlin.de/unterricht-plus/arbeitsgemeinschaften/maker-space-studio-einszwovier/), Aron was also able to test his Master’s thesis on design practice as a peer-learning format in school education.
|
||||
|
||||
|
||||
Read up a full [bio](https://aron.petau.net/pages/cv) here:
|
||||
|
||||
|
||||
### Friedrich
|
||||
|
@ -91,25 +86,18 @@ Read up a full [bio](/pages/cv) here:
|
|||
|
||||
</aside>
|
||||
|
||||
#### Education:
|
||||
Friedrich Weber Goizel first studied Fine Arts at the [Berlin University of the Arts (UdK)](https://www.udk-berlin.de/).
|
||||
He later pursued studies in [Humanoid Robotics](https://www.bht-berlin.de/b-hrob) (BHT) as well as in [Design and Computation](https://www.newpractice.net/study).
|
||||
|
||||
2014-2015 Studies of Fine Arts, Hochschule der Künste Braunschweig, sculpture
|
||||
In 2022, he was a fellow of the Cultural Foundation’s program *“dive in. Program for Digital Interactions”*, where he explored the use of robotics in public libraries.
|
||||
Since then, he has been independently leading “Making” workshops in various libraries across Berlin.
|
||||
|
||||
2015-2019 Studies of Fine Arts, Universität der Künste Berlin, Concept and New Media
|
||||
As a workshop facilitator, he also works with the [Junge Tüftler*innen, Berlin](https://junge-tueftler.de) initiative, running programs at neighborhood libraries, makerspaces, and institutions such as the Futurium.
|
||||
Alongside Aron, he co-leads the makerspace [studio einszwovier](https://www.gvb-berlin.de/unterricht-plus/arbeitsgemeinschaften/maker-space-studio-einszwovier/) at a Berlin secondary school and also works as a conceptual and media artist.
|
||||
|
||||
2019 Master of Fine Arts
|
||||
What matters most to him is sparking enthusiasm for technology, providing easy points of entry, experimenting together, and creating a learning environment where playful exploration leads to a creative engagement with technology.
|
||||
|
||||
2018-2021 Studies of humanoid Robotics, Berliner Hochschule für Technik
|
||||
|
||||
2022 Studies of Design & Computation, Technische Universität Berlin & Universität der Künste Berlin
|
||||
|
||||
#### Work:
|
||||
|
||||
2019-2021 Visitor service at Futurium Berlin
|
||||
|
||||
2021-2022 Visitor service and exhibition supervisor at GID Berlin (Futurium)
|
||||
|
||||
2022 Artistic Research Scholarship "KuRoBi4all" (Art, Robotics, Library for all); Hochschule für Wirtschaft und Recht Berlin, Stadtbibliotheken Pankow Berlin, Artspring Berlin
|
||||
Engage more with Friedrich [here](https://friedrichwebergoizel.com).
|
||||
|
||||
|
||||
---
|
||||
|
|
BIN
public/404.gif
Before Width: | Height: | Size: 4 KiB |
BIN
public/404.png
Before Width: | Height: | Size: 340 B |
Before Width: | Height: | Size: 28 KiB |
|
@ -1,9 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
|
||||
<title>Studio UMZU</title>
|
||||
<link rel="self" type="application/atom+xml" href="https://studio-umzu.de/atom.xml"/>
|
||||
<link rel="alternate" type="text/html" href="https://studio-umzu.de/"/>
|
||||
<generator uri="https://www.getzola.org/">Zola</generator>
|
||||
|
||||
<id>https://studio-umzu.de/atom.xml</id>
|
||||
</feed>
|
1
public/auto-render.min.js
vendored
|
@ -1 +0,0 @@
|
|||
!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}},n={};function r(e){var o=n[e];if(void 0!==o)return o.exports;var i=n[e]={exports:{}};return t[e](i,i.exports,r),i.exports}r.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return r.d(t,{a:t}),t},r.d=function(e,t){for(var n in t)r.o(t,n)&&!r.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},r.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)};var o={};return function(){r.d(o,{default:function(){return d}});var e=r(771),t=r.n(e);const n=function(e,t,n){let r=n,o=0;const i=e.length;for(;r<t.length;){const n=t[r];if(o<=0&&t.slice(r,r+i)===e)return r;"\\"===n?r++:"{"===n?o++:"}"===n&&o--,r++}return-1},i=/^\\begin{/;var a=function(e,t){let r;const o=[],a=new RegExp("("+t.map((e=>e.left.replace(/[-/\\^$*+?.()|[\]{}]/g,"\\$&"))).join("|")+")");for(;r=e.search(a),-1!==r;){r>0&&(o.push({type:"text",data:e.slice(0,r)}),e=e.slice(r));const a=t.findIndex((t=>e.startsWith(t.left)));if(r=n(t[a].right,e,t[a].left.length),-1===r)break;const l=e.slice(0,r+t[a].right.length),s=i.test(l)?l:e.slice(t[a].left.length,r);o.push({type:"math",data:s,rawData:l,display:t[a].display}),e=e.slice(r+t[a].right.length)}return""!==e&&o.push({type:"text",data:e}),o};const l=function(e,n){const r=a(e,n.delimiters);if(1===r.length&&"text"===r[0].type)return null;const o=document.createDocumentFragment();for(let e=0;e<r.length;e++)if("text"===r[e].type)o.appendChild(document.createTextNode(r[e].data));else{const i=document.createElement("span");let a=r[e].data;n.displayMode=r[e].display;try{n.preProcess&&(a=n.preProcess(a)),t().render(a,i,n)}catch(i){if(!(i instanceof t().ParseError))throw i;n.errorCallback("KaTeX auto-render: Failed to parse `"+r[e].data+"` with ",i),o.appendChild(document.createTextNode(r[e].rawData));continue}o.appendChild(i)}return o},s=function(e,t){for(let n=0;n<e.childNodes.length;n++){const r=e.childNodes[n];if(3===r.nodeType){let o=r.textContent,i=r.nextSibling,a=0;for(;i&&i.nodeType===Node.TEXT_NODE;)o+=i.textContent,i=i.nextSibling,a++;const s=l(o,t);if(s){for(let e=0;e<a;e++)r.nextSibling.remove();n+=s.childNodes.length-1,e.replaceChild(s,r)}else n+=a}else if(1===r.nodeType){const e=" "+r.className+" ";-1===t.ignoredTags.indexOf(r.nodeName.toLowerCase())&&t.ignoredClasses.every((t=>-1===e.indexOf(" "+t+" ")))&&s(r,t)}}};var d=function(e,t){if(!e)throw new Error("No element provided to render");const n={};for(const e in t)t.hasOwnProperty(e)&&(n[e]=t[e]);n.delimiters=n.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}],n.ignoredTags=n.ignoredTags||["script","noscript","style","textarea","pre","code","option"],n.ignoredClasses=n.ignoredClasses||[],n.errorCallback=n.errorCallback||console.error,n.macros=n.macros||{},s(e,n)}}(),o=o.default}()}));
|
BIN
public/card.png
Before Width: | Height: | Size: 1.2 MiB |
|
@ -1,27 +0,0 @@
|
|||
const closable = document.querySelectorAll("details.closable");
|
||||
|
||||
closable.forEach((detail) => {
|
||||
detail.addEventListener("toggle", () => {
|
||||
if (detail.open) setTargetDetail(detail);
|
||||
});
|
||||
});
|
||||
|
||||
function setTargetDetail(targetDetail) {
|
||||
closable.forEach((detail) => {
|
||||
if (detail !== targetDetail) {
|
||||
detail.open = false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
document.addEventListener("click", function (event) {
|
||||
const isClickInsideDetail = [...closable].some((detail) =>
|
||||
detail.contains(event.target)
|
||||
);
|
||||
|
||||
if (!isClickInsideDetail) {
|
||||
closable.forEach((detail) => {
|
||||
detail.open = false;
|
||||
});
|
||||
}
|
||||
});
|
|
@ -1,406 +0,0 @@
|
|||
// Taken from https://carlschwan.eu/2020/12/29/adding-comments-to-your-static-blog-with-mastodon/
|
||||
// Attachment, card, and spoiler code taken from https://github.com/cassidyjames/cassidyjames.github.io/blob/99782788a7e3ba3cc52d6803010873abd1b02b9e/_includes/comments.html#L251-L296
|
||||
|
||||
let blogPostAuthorText = document.getElementById("blog-post-author-text").textContent;
|
||||
let boostsFromText = document.getElementById("boosts-from-text").textContent;
|
||||
let dateLocale = document.getElementById("date-locale").textContent;
|
||||
let favesFromText = document.getElementById("faves-from-text").textContent;
|
||||
let host = document.getElementById("host").textContent;
|
||||
let id = document.getElementById("id").textContent;
|
||||
let lazyAsyncImage = document.getElementById("lazy-async-image").textContent;
|
||||
let loadingText = document.getElementById("loading-text").textContent;
|
||||
let noCommentsText = document.getElementById("no-comments-text").textContent;
|
||||
let relAttributes = document.getElementById("rel-attributes").textContent;
|
||||
let reloadText = document.getElementById("reload-text").textContent;
|
||||
let sensitiveText = document.getElementById("sensitive-text").textContent;
|
||||
let user = document.getElementById("user").textContent;
|
||||
let viewCommentText = document.getElementById("view-comment-text").textContent;
|
||||
let viewProfileText = document.getElementById("view-profile-text").textContent;
|
||||
|
||||
document.getElementById("load-comments").addEventListener("click", loadComments);
|
||||
|
||||
function escapeHtml(unsafe) {
|
||||
return unsafe
|
||||
.replace(/&/g, "&")
|
||||
.replace(/</g, "<")
|
||||
.replace(/>/g, ">")
|
||||
.replace(/"/g, """)
|
||||
.replace(/'/g, "'");
|
||||
}
|
||||
function emojify(input, emojis) {
|
||||
let output = input;
|
||||
|
||||
emojis.forEach((emoji) => {
|
||||
let picture = document.createElement("picture");
|
||||
|
||||
let source = document.createElement("source");
|
||||
source.setAttribute("srcset", escapeHtml(emoji.url));
|
||||
source.setAttribute("media", "(prefers-reduced-motion: no-preference)");
|
||||
|
||||
let img = document.createElement("img");
|
||||
img.className = "emoji";
|
||||
img.setAttribute("src", escapeHtml(emoji.static_url));
|
||||
img.setAttribute("alt", `:${emoji.shortcode}:`);
|
||||
img.setAttribute("title", `:${emoji.shortcode}:`);
|
||||
if (lazyAsyncImage == "true") {
|
||||
img.setAttribute("decoding", "async");
|
||||
img.setAttribute("loading", "lazy");
|
||||
}
|
||||
|
||||
picture.appendChild(source);
|
||||
picture.appendChild(img);
|
||||
|
||||
output = output.replace(`:${emoji.shortcode}:`, picture.outerHTML);
|
||||
});
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
function loadComments() {
|
||||
let commentsWrapper = document.getElementById("comments-wrapper");
|
||||
commentsWrapper.innerHTML = "";
|
||||
|
||||
let loadCommentsButton = document.getElementById("load-comments");
|
||||
loadCommentsButton.innerHTML = loadingText;
|
||||
loadCommentsButton.disabled = true;
|
||||
|
||||
fetch(`https://${host}/api/v1/statuses/${id}/context`)
|
||||
.then(function (response) {
|
||||
return response.json();
|
||||
})
|
||||
.then(function (data) {
|
||||
let descendants = data["descendants"];
|
||||
if (
|
||||
descendants &&
|
||||
Array.isArray(descendants) &&
|
||||
descendants.length > 0
|
||||
) {
|
||||
commentsWrapper.innerHTML = "";
|
||||
|
||||
descendants.forEach(function (status) {
|
||||
console.log(descendants);
|
||||
if (status.account.display_name.length > 0) {
|
||||
status.account.display_name = escapeHtml(
|
||||
status.account.display_name
|
||||
);
|
||||
status.account.display_name = emojify(
|
||||
status.account.display_name,
|
||||
status.account.emojis
|
||||
);
|
||||
} else {
|
||||
status.account.display_name = status.account.username;
|
||||
}
|
||||
|
||||
let instance = "";
|
||||
if (status.account.acct.includes("@")) {
|
||||
instance = status.account.acct.split("@")[1];
|
||||
} else {
|
||||
instance = host;
|
||||
}
|
||||
|
||||
const isReply = status.in_reply_to_id !== id;
|
||||
|
||||
let op = false;
|
||||
if (status.account.acct == user) {
|
||||
op = true;
|
||||
}
|
||||
|
||||
status.content = emojify(status.content, status.emojis);
|
||||
|
||||
let comment = document.createElement("article");
|
||||
comment.id = `comment-${status.id}`;
|
||||
comment.className = isReply ? "comment comment-reply" : "comment";
|
||||
comment.setAttribute("itemprop", "comment");
|
||||
comment.setAttribute("itemtype", "http://schema.org/Comment");
|
||||
|
||||
let avatarSource = document.createElement("source");
|
||||
avatarSource.setAttribute(
|
||||
"srcset",
|
||||
escapeHtml(status.account.avatar)
|
||||
);
|
||||
avatarSource.setAttribute(
|
||||
"media",
|
||||
"(prefers-reduced-motion: no-preference)"
|
||||
);
|
||||
|
||||
let avatarImg = document.createElement("img");
|
||||
avatarImg.className = "avatar";
|
||||
avatarImg.setAttribute(
|
||||
"src",
|
||||
escapeHtml(status.account.avatar_static)
|
||||
);
|
||||
avatarImg.setAttribute(
|
||||
"alt",
|
||||
`@${status.account.username}@${instance} avatar`
|
||||
);
|
||||
if (lazyAsyncImage == "true") {
|
||||
avatarImg.setAttribute("decoding", "async");
|
||||
avatarImg.setAttribute("loading", "lazy");
|
||||
}
|
||||
|
||||
let avatarPicture = document.createElement("picture");
|
||||
avatarPicture.appendChild(avatarSource);
|
||||
avatarPicture.appendChild(avatarImg);
|
||||
|
||||
let avatar = document.createElement("a");
|
||||
avatar.className = "avatar-link";
|
||||
avatar.setAttribute("href", status.account.url);
|
||||
avatar.setAttribute("rel", relAttributes);
|
||||
avatar.setAttribute(
|
||||
"title",
|
||||
`${viewProfileText} @${status.account.username}@${instance}`
|
||||
);
|
||||
avatar.appendChild(avatarPicture);
|
||||
comment.appendChild(avatar);
|
||||
|
||||
let instanceBadge = document.createElement("a");
|
||||
instanceBadge.className = "instance";
|
||||
instanceBadge.setAttribute("href", status.account.url);
|
||||
instanceBadge.setAttribute(
|
||||
"title",
|
||||
`@${status.account.username}@${instance}`
|
||||
);
|
||||
instanceBadge.setAttribute("rel", relAttributes);
|
||||
instanceBadge.textContent = instance;
|
||||
|
||||
let display = document.createElement("span");
|
||||
display.className = "display";
|
||||
display.setAttribute("itemprop", "author");
|
||||
display.setAttribute("itemtype", "http://schema.org/Person");
|
||||
display.innerHTML = status.account.display_name;
|
||||
|
||||
let header = document.createElement("header");
|
||||
header.className = "author";
|
||||
header.appendChild(display);
|
||||
header.appendChild(instanceBadge);
|
||||
comment.appendChild(header);
|
||||
|
||||
let permalink = document.createElement("a");
|
||||
permalink.setAttribute("href", status.url);
|
||||
permalink.setAttribute("itemprop", "url");
|
||||
permalink.setAttribute("title", `${viewCommentText} ${instance}`);
|
||||
permalink.setAttribute("rel", relAttributes);
|
||||
permalink.textContent = new Date(
|
||||
status.created_at
|
||||
).toLocaleString(dateLocale, {
|
||||
dateStyle: "long",
|
||||
timeStyle: "short",
|
||||
});
|
||||
|
||||
let timestamp = document.createElement("time");
|
||||
timestamp.setAttribute("datetime", status.created_at);
|
||||
timestamp.appendChild(permalink);
|
||||
permalink.classList.add("external");
|
||||
comment.appendChild(timestamp);
|
||||
|
||||
let main = document.createElement("main");
|
||||
main.setAttribute("itemprop", "text");
|
||||
|
||||
if (status.sensitive == true || status.spoiler_text != "") {
|
||||
let summary = document.createElement("summary");
|
||||
if (status.spoiler_text == "") {
|
||||
status.spoiler_text == sensitiveText;
|
||||
}
|
||||
summary.innerHTML = status.spoiler_text;
|
||||
|
||||
let spoiler = document.createElement("details");
|
||||
spoiler.appendChild(summary);
|
||||
spoiler.innerHTML += status.content;
|
||||
|
||||
main.appendChild(spoiler);
|
||||
} else {
|
||||
main.innerHTML = status.content;
|
||||
}
|
||||
comment.appendChild(main);
|
||||
|
||||
let attachments = status.media_attachments;
|
||||
let SUPPORTED_MEDIA = ["image", "video", "gifv", "audio"];
|
||||
let media = document.createElement("div");
|
||||
media.className = "attachments";
|
||||
if (
|
||||
attachments &&
|
||||
Array.isArray(attachments) &&
|
||||
attachments.length > 0
|
||||
) {
|
||||
attachments.forEach((attachment) => {
|
||||
if (SUPPORTED_MEDIA.includes(attachment.type)) {
|
||||
|
||||
let mediaElement;
|
||||
switch (attachment.type) {
|
||||
case "image":
|
||||
mediaElement = document.createElement("img");
|
||||
mediaElement.setAttribute("src", attachment.preview_url);
|
||||
|
||||
if (attachment.description != null) {
|
||||
mediaElement.setAttribute("alt", attachment.description);
|
||||
mediaElement.setAttribute("title", attachment.description);
|
||||
}
|
||||
|
||||
if (lazyAsyncImage == "true") {
|
||||
mediaElement.setAttribute("decoding", "async");
|
||||
mediaElement.setAttribute("loading", "lazy");
|
||||
}
|
||||
|
||||
if (status.sensitive == true) {
|
||||
mediaElement.classList.add("spoiler");
|
||||
}
|
||||
|
||||
media.appendChild(mediaElement);
|
||||
break;
|
||||
|
||||
case "video":
|
||||
mediaElement = document.createElement("video");
|
||||
mediaElement.setAttribute("src", attachment.url);
|
||||
mediaElement.setAttribute("controls", "");
|
||||
|
||||
if (attachment.description != null) {
|
||||
mediaElement.setAttribute("aria-title", attachment.description);
|
||||
mediaElement.setAttribute("title", attachment.description);
|
||||
}
|
||||
|
||||
if (status.sensitive == true) {
|
||||
mediaElement.classList.add("spoiler");
|
||||
}
|
||||
|
||||
media.appendChild(mediaElement);
|
||||
break;
|
||||
|
||||
case "gifv":
|
||||
mediaElement = document.createElement("video");
|
||||
mediaElement.setAttribute("src", attachment.url);
|
||||
mediaElement.setAttribute("autoplay", "");
|
||||
mediaElement.setAttribute("playsinline", "");
|
||||
mediaElement.setAttribute("loop", "");
|
||||
|
||||
if (attachment.description != null) {
|
||||
mediaElement.setAttribute("aria-title", attachment.description);
|
||||
mediaElement.setAttribute("title", attachment.description);
|
||||
}
|
||||
|
||||
if (status.sensitive == true) {
|
||||
mediaElement.classList.add("spoiler");
|
||||
}
|
||||
|
||||
media.appendChild(mediaElement);
|
||||
break;
|
||||
|
||||
case "audio":
|
||||
mediaElement = document.createElement("audio");
|
||||
mediaElement.setAttribute("src", attachment.url);
|
||||
mediaElement.setAttribute("controls", "");
|
||||
|
||||
if (attachment.description != null) {
|
||||
mediaElement.setAttribute("aria-title", attachment.description);
|
||||
mediaElement.setAttribute("title", attachment.description);
|
||||
}
|
||||
|
||||
media.appendChild(mediaElement);
|
||||
break;
|
||||
}
|
||||
|
||||
let mediaLink = document.createElement("a");
|
||||
mediaLink.setAttribute("href", attachment.url);
|
||||
mediaLink.setAttribute("rel", relAttributes);
|
||||
mediaLink.appendChild(mediaElement);
|
||||
|
||||
media.appendChild(mediaLink);
|
||||
}
|
||||
});
|
||||
|
||||
comment.appendChild(media);
|
||||
}
|
||||
|
||||
let interactions = document.createElement("footer");
|
||||
|
||||
let boosts = document.createElement("a");
|
||||
boosts.className = "boosts";
|
||||
boosts.setAttribute("href", `${status.url}/reblogs`);
|
||||
boosts.setAttribute("title", `${boostsFromText}`.replace("$INSTANCE", instance));
|
||||
|
||||
let boostsIcon = document.createElement("i");
|
||||
boostsIcon.className = "icon";
|
||||
boosts.appendChild(boostsIcon);
|
||||
boosts.insertAdjacentHTML('beforeend', ` ${status.reblogs_count}`);
|
||||
interactions.appendChild(boosts);
|
||||
|
||||
let faves = document.createElement("a");
|
||||
faves.className = "faves";
|
||||
faves.setAttribute("href", `${status.url}/favourites`);
|
||||
faves.setAttribute("title", `${favesFromText}`.replace("$INSTANCE", instance));
|
||||
|
||||
let favesIcon = document.createElement("i");
|
||||
favesIcon.className = "icon";
|
||||
faves.appendChild(favesIcon);
|
||||
faves.insertAdjacentHTML('beforeend', ` ${status.favourites_count}`);
|
||||
interactions.appendChild(faves);
|
||||
comment.appendChild(interactions);
|
||||
|
||||
if (status.card != null) {
|
||||
let cardFigure = document.createElement("figure");
|
||||
|
||||
if (status.card.image != null) {
|
||||
let cardImg = document.createElement("img");
|
||||
cardImg.setAttribute("src", status.card.image);
|
||||
cardImg.classList.add("no-hover");
|
||||
cardFigure.appendChild(cardImg);
|
||||
}
|
||||
|
||||
let cardCaption = document.createElement("figcaption");
|
||||
|
||||
let cardTitle = document.createElement("strong");
|
||||
cardTitle.innerHTML = status.card.title;
|
||||
cardCaption.appendChild(cardTitle);
|
||||
|
||||
if (status.card.description != null && status.card.description.length > 0) {
|
||||
let cardDescription = document.createElement("p");
|
||||
cardDescription.innerHTML = status.card.description;
|
||||
cardCaption.appendChild(cardDescription);
|
||||
}
|
||||
|
||||
cardFigure.appendChild(cardCaption);
|
||||
|
||||
let card = document.createElement("a");
|
||||
card.className = "card";
|
||||
card.setAttribute("href", status.card.url);
|
||||
card.setAttribute("rel", relAttributes);
|
||||
card.appendChild(cardFigure);
|
||||
|
||||
comment.appendChild(card);
|
||||
}
|
||||
|
||||
if (op === true) {
|
||||
comment.classList.add("op");
|
||||
|
||||
avatar.classList.add("op");
|
||||
avatar.setAttribute(
|
||||
"title",
|
||||
`${blogPostAuthorText}: ` + avatar.getAttribute("title")
|
||||
);
|
||||
|
||||
instanceBadge.classList.add("op");
|
||||
instanceBadge.setAttribute(
|
||||
"title",
|
||||
`${blogPostAuthorText}: ` + instanceBadge.getAttribute("title")
|
||||
);
|
||||
}
|
||||
|
||||
commentsWrapper.innerHTML += comment.outerHTML;
|
||||
});
|
||||
}
|
||||
|
||||
else {
|
||||
var statusText = document.createElement("p");
|
||||
statusText.innerHTML = noCommentsText;
|
||||
statusText.setAttribute("id", "comments-status");
|
||||
commentsWrapper.appendChild(statusText);
|
||||
}
|
||||
|
||||
loadCommentsButton.innerHTML = reloadText;
|
||||
})
|
||||
.catch(function (error) {
|
||||
console.error('Error loading comments:', error);
|
||||
})
|
||||
.finally(function () {
|
||||
loadCommentsButton.disabled = false;
|
||||
});
|
||||
}
|
|
@ -1,57 +0,0 @@
|
|||
// Based on https://www.roboleary.net/2022/01/13/copy-code-to-clipboard-blog.html
|
||||
document.addEventListener("DOMContentLoaded", function () {
|
||||
let blocks = document.querySelectorAll("pre[class^='language-']");
|
||||
|
||||
blocks.forEach((block) => {
|
||||
if (navigator.clipboard) {
|
||||
// Code block header title
|
||||
let title = document.createElement("span");
|
||||
let lang = block.getAttribute("data-lang");
|
||||
title.innerHTML = lang;
|
||||
|
||||
// Copy button icon
|
||||
let icon = document.createElement("i");
|
||||
icon.classList.add("icon");
|
||||
|
||||
// Copy button
|
||||
let button = document.createElement("button");
|
||||
let copyCodeText = document.getElementById("copy-code-text").textContent;
|
||||
button.setAttribute("title", copyCodeText)
|
||||
button.appendChild(icon);
|
||||
|
||||
// Code block header
|
||||
let header = document.createElement("div");
|
||||
header.classList.add("header");
|
||||
header.appendChild(title);
|
||||
header.appendChild(button);
|
||||
|
||||
// Container that holds header and the code block itself
|
||||
let container = document.createElement("div");
|
||||
container.classList.add("pre-container");
|
||||
container.appendChild(header);
|
||||
|
||||
// Move code block into the container
|
||||
block.parentNode.insertBefore(container, block);
|
||||
container.appendChild(block);
|
||||
|
||||
button.addEventListener("click", async () => {
|
||||
await copyCode(block, header, button); // Pass the button here
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
async function copyCode(block, header, button) {
|
||||
let code = block.querySelector("code");
|
||||
let text = code.innerText;
|
||||
|
||||
await navigator.clipboard.writeText(text);
|
||||
|
||||
header.classList.add("active");
|
||||
button.setAttribute("disabled", true);
|
||||
|
||||
header.addEventListener("animationend", () => {
|
||||
header.classList.remove("active");
|
||||
button.removeAttribute("disabled");
|
||||
}, { once: true });
|
||||
}
|
||||
});
|
271
public/count.js
|
@ -1,271 +0,0 @@
|
|||
// GoatCounter: https://www.goatcounter.com
|
||||
// This file is released under the ISC license: https://opensource.org/licenses/ISC
|
||||
;(function() {
|
||||
'use strict';
|
||||
|
||||
if (window.goatcounter && window.goatcounter.vars) // Compatibility with very old version; do not use.
|
||||
window.goatcounter = window.goatcounter.vars
|
||||
else
|
||||
window.goatcounter = window.goatcounter || {}
|
||||
|
||||
// Load settings from data-goatcounter-settings.
|
||||
var s = document.querySelector('script[data-goatcounter]')
|
||||
if (s && s.dataset.goatcounterSettings) {
|
||||
try { var set = JSON.parse(s.dataset.goatcounterSettings) }
|
||||
catch (err) { console.error('invalid JSON in data-goatcounter-settings: ' + err) }
|
||||
for (var k in set)
|
||||
if (['no_onload', 'no_events', 'allow_local', 'allow_frame', 'path', 'title', 'referrer', 'event'].indexOf(k) > -1)
|
||||
window.goatcounter[k] = set[k]
|
||||
}
|
||||
|
||||
var enc = encodeURIComponent
|
||||
|
||||
// Get all data we're going to send off to the counter endpoint.
|
||||
var get_data = function(vars) {
|
||||
var data = {
|
||||
p: (vars.path === undefined ? goatcounter.path : vars.path),
|
||||
r: (vars.referrer === undefined ? goatcounter.referrer : vars.referrer),
|
||||
t: (vars.title === undefined ? goatcounter.title : vars.title),
|
||||
e: !!(vars.event || goatcounter.event),
|
||||
s: [window.screen.width, window.screen.height, (window.devicePixelRatio || 1)],
|
||||
b: is_bot(),
|
||||
q: location.search,
|
||||
}
|
||||
|
||||
var rcb, pcb, tcb // Save callbacks to apply later.
|
||||
if (typeof(data.r) === 'function') rcb = data.r
|
||||
if (typeof(data.t) === 'function') tcb = data.t
|
||||
if (typeof(data.p) === 'function') pcb = data.p
|
||||
|
||||
if (is_empty(data.r)) data.r = document.referrer
|
||||
if (is_empty(data.t)) data.t = document.title
|
||||
if (is_empty(data.p)) data.p = get_path()
|
||||
|
||||
if (rcb) data.r = rcb(data.r)
|
||||
if (tcb) data.t = tcb(data.t)
|
||||
if (pcb) data.p = pcb(data.p)
|
||||
return data
|
||||
}
|
||||
|
||||
// Check if a value is "empty" for the purpose of get_data().
|
||||
var is_empty = function(v) { return v === null || v === undefined || typeof(v) === 'function' }
|
||||
|
||||
// See if this looks like a bot; there is some additional filtering on the
|
||||
// backend, but these properties can't be fetched from there.
|
||||
var is_bot = function() {
|
||||
// Headless browsers are probably a bot.
|
||||
var w = window, d = document
|
||||
if (w.callPhantom || w._phantom || w.phantom)
|
||||
return 150
|
||||
if (w.__nightmare)
|
||||
return 151
|
||||
if (d.__selenium_unwrapped || d.__webdriver_evaluate || d.__driver_evaluate)
|
||||
return 152
|
||||
if (navigator.webdriver)
|
||||
return 153
|
||||
return 0
|
||||
}
|
||||
|
||||
// Object to urlencoded string, starting with a ?.
|
||||
var urlencode = function(obj) {
|
||||
var p = []
|
||||
for (var k in obj)
|
||||
if (obj[k] !== '' && obj[k] !== null && obj[k] !== undefined && obj[k] !== false)
|
||||
p.push(enc(k) + '=' + enc(obj[k]))
|
||||
return '?' + p.join('&')
|
||||
}
|
||||
|
||||
// Show a warning in the console.
|
||||
var warn = function(msg) {
|
||||
if (console && 'warn' in console)
|
||||
console.warn('goatcounter: ' + msg)
|
||||
}
|
||||
|
||||
// Get the endpoint to send requests to.
|
||||
var get_endpoint = function() {
|
||||
var s = document.querySelector('script[data-goatcounter]')
|
||||
if (s && s.dataset.goatcounter)
|
||||
return s.dataset.goatcounter
|
||||
return (goatcounter.endpoint || window.counter) // counter is for compat; don't use.
|
||||
}
|
||||
|
||||
// Get current path.
|
||||
var get_path = function() {
|
||||
var loc = location,
|
||||
c = document.querySelector('link[rel="canonical"][href]')
|
||||
if (c) { // May be relative or point to different domain.
|
||||
var a = document.createElement('a')
|
||||
a.href = c.href
|
||||
if (a.hostname.replace(/^www\./, '') === location.hostname.replace(/^www\./, ''))
|
||||
loc = a
|
||||
}
|
||||
return (loc.pathname + loc.search) || '/'
|
||||
}
|
||||
|
||||
// Run function after DOM is loaded.
|
||||
var on_load = function(f) {
|
||||
if (document.body === null)
|
||||
document.addEventListener('DOMContentLoaded', function() { f() }, false)
|
||||
else
|
||||
f()
|
||||
}
|
||||
|
||||
// Filter some requests that we (probably) don't want to count.
|
||||
goatcounter.filter = function() {
|
||||
if ('visibilityState' in document && document.visibilityState === 'prerender')
|
||||
return 'visibilityState'
|
||||
if (!goatcounter.allow_frame && location !== parent.location)
|
||||
return 'frame'
|
||||
if (!goatcounter.allow_local && location.hostname.match(/(localhost$|^127\.|^10\.|^172\.(1[6-9]|2[0-9]|3[0-1])\.|^192\.168\.|^0\.0\.0\.0$)/))
|
||||
return 'localhost'
|
||||
if (!goatcounter.allow_local && location.protocol === 'file:')
|
||||
return 'localfile'
|
||||
if (localStorage && localStorage.getItem('skipgc') === 't')
|
||||
return 'disabled with #toggle-goatcounter'
|
||||
return false
|
||||
}
|
||||
|
||||
// Get URL to send to GoatCounter.
|
||||
window.goatcounter.url = function(vars) {
|
||||
var data = get_data(vars || {})
|
||||
if (data.p === null) // null from user callback.
|
||||
return
|
||||
data.rnd = Math.random().toString(36).substr(2, 5) // Browsers don't always listen to Cache-Control.
|
||||
|
||||
var endpoint = get_endpoint()
|
||||
if (!endpoint)
|
||||
return warn('no endpoint found')
|
||||
|
||||
return endpoint + urlencode(data)
|
||||
}
|
||||
|
||||
// Count a hit.
|
||||
window.goatcounter.count = function(vars) {
|
||||
var f = goatcounter.filter()
|
||||
if (f)
|
||||
return warn('not counting because of: ' + f)
|
||||
var url = goatcounter.url(vars)
|
||||
if (!url)
|
||||
return warn('not counting because path callback returned null')
|
||||
|
||||
if (!navigator.sendBeacon(url)) {
|
||||
// This mostly fails due to being blocked by CSP; try again with an
|
||||
// image-based fallback.
|
||||
var img = document.createElement('img')
|
||||
img.src = url
|
||||
img.style.position = 'absolute' // Affect layout less.
|
||||
img.style.bottom = '0px'
|
||||
img.style.width = '1px'
|
||||
img.style.height = '1px'
|
||||
img.loading = 'eager'
|
||||
img.setAttribute('alt', '')
|
||||
img.setAttribute('aria-hidden', 'true')
|
||||
|
||||
var rm = function() { if (img && img.parentNode) img.parentNode.removeChild(img) }
|
||||
img.addEventListener('load', rm, false)
|
||||
document.body.appendChild(img)
|
||||
}
|
||||
}
|
||||
|
||||
// Get a query parameter.
|
||||
window.goatcounter.get_query = function(name) {
|
||||
var s = location.search.substr(1).split('&')
|
||||
for (var i = 0; i < s.length; i++)
|
||||
if (s[i].toLowerCase().indexOf(name.toLowerCase() + '=') === 0)
|
||||
return s[i].substr(name.length + 1)
|
||||
}
|
||||
|
||||
// Track click events.
|
||||
window.goatcounter.bind_events = function() {
|
||||
if (!document.querySelectorAll) // Just in case someone uses an ancient browser.
|
||||
return
|
||||
|
||||
var send = function(elem) {
|
||||
return function() {
|
||||
goatcounter.count({
|
||||
event: true,
|
||||
path: (elem.dataset.goatcounterClick || elem.name || elem.id || ''),
|
||||
title: (elem.dataset.goatcounterTitle || elem.title || (elem.innerHTML || '').substr(0, 200) || ''),
|
||||
referrer: (elem.dataset.goatcounterReferrer || elem.dataset.goatcounterReferral || ''),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Array.prototype.slice.call(document.querySelectorAll("*[data-goatcounter-click]")).forEach(function(elem) {
|
||||
if (elem.dataset.goatcounterBound)
|
||||
return
|
||||
var f = send(elem)
|
||||
elem.addEventListener('click', f, false)
|
||||
elem.addEventListener('auxclick', f, false) // Middle click.
|
||||
elem.dataset.goatcounterBound = 'true'
|
||||
})
|
||||
}
|
||||
|
||||
// Add a "visitor counter" frame or image.
|
||||
window.goatcounter.visit_count = function(opt) {
|
||||
on_load(function() {
|
||||
opt = opt || {}
|
||||
opt.type = opt.type || 'html'
|
||||
opt.append = opt.append || 'body'
|
||||
opt.path = opt.path || get_path()
|
||||
opt.attr = opt.attr || {width: '200', height: (opt.no_branding ? '60' : '80')}
|
||||
|
||||
opt.attr['src'] = get_endpoint() + 'er/' + enc(opt.path) + '.' + enc(opt.type) + '?'
|
||||
if (opt.no_branding) opt.attr['src'] += '&no_branding=1'
|
||||
if (opt.style) opt.attr['src'] += '&style=' + enc(opt.style)
|
||||
if (opt.start) opt.attr['src'] += '&start=' + enc(opt.start)
|
||||
if (opt.end) opt.attr['src'] += '&end=' + enc(opt.end)
|
||||
|
||||
var tag = {png: 'img', svg: 'img', html: 'iframe'}[opt.type]
|
||||
if (!tag)
|
||||
return warn('visit_count: unknown type: ' + opt.type)
|
||||
|
||||
if (opt.type === 'html') {
|
||||
opt.attr['frameborder'] = '0'
|
||||
opt.attr['scrolling'] = 'no'
|
||||
}
|
||||
|
||||
var d = document.createElement(tag)
|
||||
for (var k in opt.attr)
|
||||
d.setAttribute(k, opt.attr[k])
|
||||
|
||||
var p = document.querySelector(opt.append)
|
||||
if (!p)
|
||||
return warn('visit_count: append not found: ' + opt.append)
|
||||
p.appendChild(d)
|
||||
})
|
||||
}
|
||||
|
||||
// Make it easy to skip your own views.
|
||||
if (location.hash === '#toggle-goatcounter') {
|
||||
if (localStorage.getItem('skipgc') === 't') {
|
||||
localStorage.removeItem('skipgc', 't')
|
||||
alert('GoatCounter tracking is now ENABLED in this browser.')
|
||||
}
|
||||
else {
|
||||
localStorage.setItem('skipgc', 't')
|
||||
alert('GoatCounter tracking is now DISABLED in this browser until ' + location + ' is loaded again.')
|
||||
}
|
||||
}
|
||||
|
||||
if (!goatcounter.no_onload)
|
||||
on_load(function() {
|
||||
// 1. Page is visible, count request.
|
||||
// 2. Page is not yet visible; wait until it switches to 'visible' and count.
|
||||
// See #487
|
||||
if (!('visibilityState' in document) || document.visibilityState === 'visible')
|
||||
goatcounter.count()
|
||||
else {
|
||||
var f = function(e) {
|
||||
if (document.visibilityState !== 'visible')
|
||||
return
|
||||
document.removeEventListener('visibilitychange', f)
|
||||
goatcounter.count()
|
||||
}
|
||||
document.addEventListener('visibilitychange', f)
|
||||
}
|
||||
|
||||
if (!goatcounter.no_events)
|
||||
goatcounter.bind_events()
|
||||
})
|
||||
})();
|
|
@ -1,48 +0,0 @@
|
|||
#image-gallery {
|
||||
margin: 2rem 0;
|
||||
}
|
||||
|
||||
.gallery {
|
||||
column-count: 3;
|
||||
column-gap: 1rem;
|
||||
}
|
||||
|
||||
.gallery-item {
|
||||
break-inside: avoid;
|
||||
margin-bottom: 1rem;
|
||||
text-align: center;
|
||||
list-style: none; /* ← important! */
|
||||
}
|
||||
|
||||
|
||||
.gallery-item img {
|
||||
width: 100%;
|
||||
height: auto;
|
||||
border-radius: 12px;
|
||||
box-shadow: 0 4px 8px rgba(0,0,0,0.1);
|
||||
transition: transform 0.2s ease;
|
||||
}
|
||||
|
||||
.gallery-item img:hover {
|
||||
transform: scale(1.6);
|
||||
}
|
||||
|
||||
.caption {
|
||||
font-size: 0.9rem;
|
||||
margin-top: 0.5rem;
|
||||
margin-bottom: 0; /* ← just in case */
|
||||
color: var(--fg-color);
|
||||
list-style: none; /* ← extra-safe */
|
||||
}
|
||||
|
||||
@media (max-width: 768px) {
|
||||
.gallery {
|
||||
column-count: 2;
|
||||
}
|
||||
}
|
||||
|
||||
@media (max-width: 480px) {
|
||||
.gallery {
|
||||
column-count: 1;
|
||||
}
|
||||
}
|
|
@ -1,28 +0,0 @@
|
|||
.mermaid {
|
||||
text-align: center;
|
||||
margin-top: 1.5em;
|
||||
margin-bottom: 1.5em;
|
||||
padding: 1em;
|
||||
border-radius: 0.5em;
|
||||
background-color: var(--code-bg);
|
||||
font-family: var(--code-font, monospace);
|
||||
font-size: 0.9rem;
|
||||
overflow-x: auto;
|
||||
max-width: 100%;
|
||||
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.08);
|
||||
}
|
||||
|
||||
.mermaid strong {
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.mermaid svg {
|
||||
max-width: 100%;
|
||||
height: auto;
|
||||
}
|
||||
|
||||
@media (prefers-color-scheme: dark) {
|
||||
.mermaid {
|
||||
background-color: var(--code-bg-dark, #2d2d2d);
|
||||
}
|
||||
}
|
|
@ -1,72 +0,0 @@
|
|||
/* Basic Layout for Skills List */
|
||||
#skills-content {
|
||||
margin: 2rem 0;
|
||||
}
|
||||
|
||||
#skills-content .category {
|
||||
margin-bottom: 3rem;
|
||||
}
|
||||
|
||||
#skills-content .category h3 {
|
||||
font-size: 1.5rem;
|
||||
font-weight: regular;
|
||||
margin-bottom: 1rem;
|
||||
}
|
||||
|
||||
/* Skills container for single-line display */
|
||||
#skills-content .skills-list {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
display: flex; /* Use flexbox for single-line display */
|
||||
flex-wrap: wrap; /* Allow skills to wrap if needed */
|
||||
gap: 1rem; /* Spacing between skills */
|
||||
}
|
||||
|
||||
/* Skill List Item */
|
||||
#skills-content .skills-list .skill {
|
||||
display: inline-flex; /* Ensures each skill is aligned inline */
|
||||
align-items: center;
|
||||
position: relative;
|
||||
cursor: pointer; /* Show pointer cursor on hover */
|
||||
text-decoration: none; /* Remove underline from links */
|
||||
color: inherit; /* Inherit color from parent */
|
||||
transition: background-color 0.3s, color 0.3s;
|
||||
}
|
||||
|
||||
|
||||
/* Skill Name */
|
||||
#skills-content .skills-list .skill span {
|
||||
display: inline-block;
|
||||
font-size: 1.2rem;
|
||||
margin-left: 0.5rem;
|
||||
line-height: 1.4;
|
||||
}
|
||||
|
||||
/* Skill Icon */
|
||||
#skills-content .skills-list .skill .skill-icon {
|
||||
margin-right: 0.5rem;
|
||||
color: var(--accent-color);
|
||||
font-size: 1.4rem;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
/* Hover Effects for Skills */
|
||||
#skills-content .skills-list .skill:hover::before {
|
||||
background: var(--accent-color-dark);
|
||||
}
|
||||
|
||||
#skills-content .skills-list .skill:hover {
|
||||
background-color: var(--accent-color-alpha);
|
||||
color: var(--fg-color); /* Change text color on hover */
|
||||
}
|
||||
|
||||
/* Skill Category Hover Effect */
|
||||
#skills-content .skills-list .skill:hover span {
|
||||
color: var(--fg-color);
|
||||
}
|
||||
|
||||
/* Optional: Customize Icon Color on Hover */
|
||||
#skills-content .skills-list .skill:hover .skill-icon {
|
||||
color: var(--fg-color);
|
||||
}
|
|
@ -1,91 +0,0 @@
|
|||
/* Basic Layout */
|
||||
#timeline-content {
|
||||
position: relative;
|
||||
margin: 2rem 0;
|
||||
padding-left: 120px;
|
||||
}
|
||||
|
||||
#timeline-content ul.timeline {
|
||||
list-style: none;
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
#timeline-content ul.timeline::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: -30px;
|
||||
top: 0;
|
||||
bottom: 0;
|
||||
width: 2px;
|
||||
background: var(--accent-color);
|
||||
}
|
||||
|
||||
/* Event List Item */
|
||||
#timeline-content li.event {
|
||||
position: relative;
|
||||
margin-bottom: 3rem;
|
||||
}
|
||||
|
||||
/* Event Circle */
|
||||
#timeline-content li.event::before {
|
||||
content: '';
|
||||
position: absolute;
|
||||
left: -39px;
|
||||
top: 5px;
|
||||
width: 16px;
|
||||
height: 16px;
|
||||
border-radius: 50%;
|
||||
background: var(--bg-color);
|
||||
border: 2px solid white;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
/* From + To Label — styled exactly like old date label */
|
||||
#timeline-content li.event::after {
|
||||
content: attr(data-from) "\A" attr(data-to);
|
||||
white-space: pre; /* ensures newline works */
|
||||
position: absolute;
|
||||
left: -160px;
|
||||
width: 100px;
|
||||
text-align: right;
|
||||
color: var(--fg-color);
|
||||
font-weight: bold;
|
||||
font-size: 0.9rem;
|
||||
line-height: 1.3;
|
||||
top: 0;
|
||||
}
|
||||
|
||||
/* Event Heading */
|
||||
#timeline-content li.event h3 {
|
||||
margin: 0 0 0.5rem 0;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
/* Event Description */
|
||||
#timeline-content li.event p {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/* Timeline Icon */
|
||||
#timeline-content .timeline-icon {
|
||||
margin-right: 0.5rem;
|
||||
color: var(--accent-color);
|
||||
font-size: 1.2rem;
|
||||
vertical-align: middle;
|
||||
}
|
||||
|
||||
/* Hover Effects */
|
||||
#timeline-content li.event:hover::before {
|
||||
background: var(--accent-color);
|
||||
}
|
||||
|
||||
#timeline-content li.event:hover {
|
||||
background-color: var(--accent-color-alpha);
|
||||
}
|
||||
|
||||
/* From + To Label Hover Effect */
|
||||
#timeline-content li.event:hover::after {
|
||||
color: var(--accent-color);
|
||||
}
|
|
@ -1,10 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="de">
|
||||
<title>Studio UMZU</title>
|
||||
<subtitle>Spielerisches Lernen mit Technikdidaktik</subtitle>
|
||||
<link rel="self" type="application/atom+xml" href="https://studio-umzu.de/de/atom.xml"/>
|
||||
<link rel="alternate" type="text/html" href="https://studio-umzu.de/"/>
|
||||
<generator uri="https://www.getzola.org/">Zola</generator>
|
||||
|
||||
<id>https://studio-umzu.de/de/atom.xml</id>
|
||||
</feed>
|
Before Width: | Height: | Size: 548 B |
|
@ -1 +0,0 @@
|
|||
@font-face{font-style:normal;font-weight:100 900;src:url("fonts/InterVariable.woff2") format("woff2");font-family:"Inter Variable";font-display:swap}@font-face{font-style:italic;font-weight:100 900;src:url("fonts/InterVariable-Italic.woff2") format("woff2");font-family:"Inter Variable";font-display:swap}@font-face{font-style:normal;font-weight:100 900;src:url("fonts/JetBrainsMono.woff2") format("woff2");font-family:"JetBrains Mono";font-display:swap}@font-face{font-style:italic;font-weight:100 900;src:url("fonts/JetBrainsMono-Italic.woff2") format("woff2");font-family:"JetBrains Mono";font-display:swap}body{font-family:"Inter Variable",var(--font-system-ui),var(--font-emoji)}h1,h2,h3,h4,h5,h6{font-weight:bold;font-family:"Inter Variable",var(--font-system-ui),var(--font-emoji)}h1{font-weight:900}pre,code,kbd,samp{font-family:"JetBrains Mono",var(--font-monospace-code)}
|
|
@ -1,8 +0,0 @@
|
|||
document.addEventListener("DOMContentLoaded", function () {
|
||||
renderMathInElement(document.body, {
|
||||
delimiters: [
|
||||
{ left: "$$", right: "$$", display: true },
|
||||
{ left: "$", right: "$", display: false },
|
||||
],
|
||||
});
|
||||
});
|
1209
public/katex.css
1
public/katex.min.js
vendored
BIN
public/logo.png
Before Width: | Height: | Size: 56 KiB |
Before Width: | Height: | Size: 96 B |
Before Width: | Height: | Size: 103 KiB |
|
@ -1,4 +0,0 @@
|
|||
User-agent: *
|
||||
Disallow:
|
||||
Allow: /
|
||||
Sitemap: https://studio-umzu.de/sitemap.xml
|
|
@ -1,12 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<rss xmlns:atom="http://www.w3.org/2005/Atom" version="2.0">
|
||||
<channel>
|
||||
<title>Studio UMZU</title>
|
||||
<link>https://studio-umzu.de/</link>
|
||||
<description></description>
|
||||
<generator>Zola</generator>
|
||||
<language>en</language>
|
||||
<atom:link href="https://studio-umzu.de/rss.xml" rel="self" type="application/rss+xml"/>
|
||||
|
||||
</channel>
|
||||
</rss>
|
|
@ -1,209 +0,0 @@
|
|||
// Based on https://github.com/getzola/zola/blob/1ac1231de1e342bbaf4d7a51a8a9a40ea152e246/docs/static/search.js
|
||||
function debounce(func, wait) {
|
||||
var timeout;
|
||||
|
||||
return function () {
|
||||
var context = this;
|
||||
var args = arguments;
|
||||
clearTimeout(timeout);
|
||||
|
||||
timeout = setTimeout(function () {
|
||||
timeout = null;
|
||||
func.apply(context, args);
|
||||
}, wait);
|
||||
};
|
||||
}
|
||||
|
||||
// Taken from mdbook
|
||||
// The strategy is as follows:
|
||||
// First, assign a value to each word in the document:
|
||||
// Words that correspond to search terms (stemmer aware): 40
|
||||
// Normal words: 2
|
||||
// First word in a sentence: 8
|
||||
// Then use a sliding window with a constant number of words and count the
|
||||
// sum of the values of the words within the window. Then use the window that got the
|
||||
// maximum sum. If there are multiple maximas, then get the last one.
|
||||
// Enclose the terms in <b>.
|
||||
function makeTeaser(body, terms) {
|
||||
var TERM_WEIGHT = 40;
|
||||
var NORMAL_WORD_WEIGHT = 2;
|
||||
var FIRST_WORD_WEIGHT = 8;
|
||||
var TEASER_MAX_WORDS = 30;
|
||||
|
||||
var stemmedTerms = terms.map(function (w) {
|
||||
return elasticlunr.stemmer(w.toLowerCase());
|
||||
});
|
||||
var termFound = false;
|
||||
var index = 0;
|
||||
var weighted = []; // contains elements of ["word", weight, index_in_document]
|
||||
|
||||
// split in sentences, then words
|
||||
var sentences = body.toLowerCase().split(". ");
|
||||
|
||||
for (var i in sentences) {
|
||||
var words = sentences[i].split(" ");
|
||||
var value = FIRST_WORD_WEIGHT;
|
||||
|
||||
for (var j in words) {
|
||||
var word = words[j];
|
||||
|
||||
if (word.length > 0) {
|
||||
for (var k in stemmedTerms) {
|
||||
if (elasticlunr.stemmer(word).startsWith(stemmedTerms[k])) {
|
||||
value = TERM_WEIGHT;
|
||||
termFound = true;
|
||||
}
|
||||
}
|
||||
weighted.push([word, value, index]);
|
||||
value = NORMAL_WORD_WEIGHT;
|
||||
}
|
||||
|
||||
index += word.length;
|
||||
index += 1; // ' ' or '.' if last word in sentence
|
||||
}
|
||||
|
||||
index += 1; // because we split at a two-char boundary '. '
|
||||
}
|
||||
|
||||
if (weighted.length === 0) {
|
||||
return body;
|
||||
}
|
||||
|
||||
var windowWeights = [];
|
||||
var windowSize = Math.min(weighted.length, TEASER_MAX_WORDS);
|
||||
// We add a window with all the weights first
|
||||
var curSum = 0;
|
||||
for (var i = 0; i < windowSize; i++) {
|
||||
curSum += weighted[i][1];
|
||||
}
|
||||
windowWeights.push(curSum);
|
||||
|
||||
for (var i = 0; i < weighted.length - windowSize; i++) {
|
||||
curSum -= weighted[i][1];
|
||||
curSum += weighted[i + windowSize][1];
|
||||
windowWeights.push(curSum);
|
||||
}
|
||||
|
||||
// If we didn't find the term, just pick the first window
|
||||
var maxSumIndex = 0;
|
||||
if (termFound) {
|
||||
var maxFound = 0;
|
||||
// backwards
|
||||
for (var i = windowWeights.length - 1; i >= 0; i--) {
|
||||
if (windowWeights[i] > maxFound) {
|
||||
maxFound = windowWeights[i];
|
||||
maxSumIndex = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var teaser = [];
|
||||
var startIndex = weighted[maxSumIndex][2];
|
||||
for (var i = maxSumIndex; i < maxSumIndex + windowSize; i++) {
|
||||
var word = weighted[i];
|
||||
if (startIndex < word[2]) {
|
||||
// missing text from index to start of `word`
|
||||
teaser.push(body.substring(startIndex, word[2]));
|
||||
startIndex = word[2];
|
||||
}
|
||||
|
||||
// add <strong> around search terms
|
||||
if (word[1] === TERM_WEIGHT) {
|
||||
teaser.push("<strong>");
|
||||
}
|
||||
startIndex = word[2] + word[0].length;
|
||||
teaser.push(body.substring(word[2], startIndex));
|
||||
|
||||
if (word[1] === TERM_WEIGHT) {
|
||||
teaser.push("</strong>");
|
||||
}
|
||||
}
|
||||
teaser.push("…");
|
||||
return teaser.join("");
|
||||
}
|
||||
|
||||
function formatSearchResultItem(item, terms) {
|
||||
return '<div class="item">'
|
||||
+ `<a href="${item.ref}">${item.doc.title}</a>`
|
||||
+ `<span>${makeTeaser(item.doc.body, terms)}</span>`
|
||||
+ '</div>';
|
||||
}
|
||||
|
||||
function initSearch() {
|
||||
var searchBar = document.getElementById("search-bar");
|
||||
var searchContainer = document.getElementById("search-container");
|
||||
var searchResults = document.getElementById("search-results");
|
||||
var MAX_ITEMS = 10;
|
||||
|
||||
var options = {
|
||||
bool: "AND",
|
||||
fields: {
|
||||
title: { boost: 2 },
|
||||
body: { boost: 1 },
|
||||
}
|
||||
};
|
||||
var currentTerm = "";
|
||||
var index;
|
||||
|
||||
var initIndex = async function () {
|
||||
if (index === undefined) {
|
||||
let searchIndex = document.getElementById("search-index").textContent;
|
||||
index = fetch(searchIndex)
|
||||
.then(
|
||||
async function (response) {
|
||||
return await elasticlunr.Index.load(await response.json());
|
||||
}
|
||||
);
|
||||
}
|
||||
let res = await index;
|
||||
return res;
|
||||
}
|
||||
|
||||
searchBar.addEventListener("keyup", debounce(async function () {
|
||||
var term = searchBar.value.trim();
|
||||
if (term === currentTerm) {
|
||||
return;
|
||||
}
|
||||
searchResults.style.display = term === "" ? "none" : "flex";
|
||||
searchResults.innerHTML = "";
|
||||
currentTerm = term;
|
||||
if (term === "") {
|
||||
return;
|
||||
}
|
||||
|
||||
var results = (await initIndex()).search(term, options);
|
||||
if (results.length === 0) {
|
||||
searchResults.style.display = "none";
|
||||
return;
|
||||
}
|
||||
|
||||
for (var i = 0; i < Math.min(results.length, MAX_ITEMS); i++) {
|
||||
searchResults.innerHTML += formatSearchResultItem(results[i], term.split(" "));
|
||||
}
|
||||
}, 150));
|
||||
|
||||
document.addEventListener("keydown", function (event) {
|
||||
if (event.key === "/") {
|
||||
event.preventDefault();
|
||||
toggleSearch();
|
||||
}
|
||||
});
|
||||
|
||||
document.getElementById("search-toggle").addEventListener("click", toggleSearch);
|
||||
}
|
||||
|
||||
function toggleSearch() {
|
||||
var searchContainer = document.getElementById("search-container");
|
||||
var searchBar = document.getElementById("search-bar");
|
||||
searchContainer.classList.toggle("active");
|
||||
searchBar.toggleAttribute("disabled");
|
||||
searchBar.focus();
|
||||
}
|
||||
|
||||
if (document.readyState === "complete" ||
|
||||
(document.readyState !== "loading" && !document.documentElement.doScroll)
|
||||
) {
|
||||
initSearch();
|
||||
} else {
|
||||
document.addEventListener("DOMContentLoaded", initSearch);
|
||||
}
|
|
@ -1,127 +0,0 @@
|
|||
// Based on https://codeberg.org/daudix/duckquill/issues/101#issuecomment-2377169
|
||||
let searchSetup = false;
|
||||
let fuse;
|
||||
|
||||
async function initIndex() {
|
||||
if (searchSetup) return;
|
||||
|
||||
const url = document.getElementById("search-index").textContent;
|
||||
const response = await fetch(url);
|
||||
|
||||
if (!response.ok) throw new Error(`HTTP error! status: ${response.status}`);
|
||||
|
||||
const options = {
|
||||
includeScore: false,
|
||||
includeMatches: true,
|
||||
ignoreLocation: true,
|
||||
threshold: 0.15,
|
||||
keys: [
|
||||
{ name: "title", weight: 3 },
|
||||
{ name: "description", weight: 2 },
|
||||
{ name: "body", weight: 1 }
|
||||
]
|
||||
};
|
||||
|
||||
fuse = new Fuse(await response.json(), options);
|
||||
searchSetup = true;
|
||||
|
||||
console.log("Search index initialized successfully");
|
||||
}
|
||||
|
||||
function toggleSearch() {
|
||||
initIndex();
|
||||
const searchBar = document.getElementById("search-bar");
|
||||
const searchContainer = document.getElementById("search-container");
|
||||
const searchResults = document.getElementById("search-results");
|
||||
searchContainer.classList.toggle("active");
|
||||
searchBar.toggleAttribute("disabled");
|
||||
searchBar.focus();
|
||||
}
|
||||
|
||||
function debounce(actual_fn, wait) {
|
||||
let timeoutId;
|
||||
|
||||
return (...args) => {
|
||||
clearTimeout(timeoutId);
|
||||
|
||||
timeoutId = setTimeout(() => {
|
||||
actual_fn(...args);
|
||||
}, wait);
|
||||
};
|
||||
};
|
||||
|
||||
function initSearch() {
|
||||
const searchBar = document.getElementById("search-bar");
|
||||
const searchResults = document.getElementById("search-results");
|
||||
const searchContainer = document.getElementById("search-container");
|
||||
const MAX_ITEMS = 10;
|
||||
const MAX_RESULTS = 4;
|
||||
|
||||
let currentTerm = "";
|
||||
|
||||
searchBar.addEventListener("keyup", (e) => {
|
||||
const searchVal = searchBar.value.trim();
|
||||
const results = fuse.search(searchVal, { limit: MAX_ITEMS });
|
||||
|
||||
let html = "";
|
||||
for (const result of results) {
|
||||
html += makeTeaser(result, searchVal);
|
||||
}
|
||||
searchResults.innerHTML = html;
|
||||
|
||||
if (html) {
|
||||
searchResults.style.display = "flex";
|
||||
} else {
|
||||
searchResults.style.display = "none";
|
||||
}
|
||||
});
|
||||
|
||||
function makeTeaser(result, searchVal) {
|
||||
const TEASER_SIZE = 20;
|
||||
let output = `<div class="search-result item"><a class="result-title" href=${result.item.url}>${result.item.title}</a>`;
|
||||
|
||||
for (const match of result.matches) {
|
||||
if (match.key === "title") continue;
|
||||
|
||||
const indices = match.indices.sort((a, b) => Math.abs(a[1] - a[0] - searchVal.length) - Math.abs(b[1] - b[0] - searchVal.length)).slice(0, MAX_RESULTS);
|
||||
const value = match.value;
|
||||
|
||||
for (const ind of indices) {
|
||||
const start = Math.max(0, ind[0] - TEASER_SIZE);
|
||||
const end = Math.min(value.length - 1, ind[1] + TEASER_SIZE);
|
||||
output += "<span>"
|
||||
+ value.substring(start, ind[0])
|
||||
+ `<strong>${value.substring(ind[0], ind[1] + 1)}</strong>`
|
||||
+ value.substring(ind[1] + 1, end)
|
||||
+ "</span>";
|
||||
}
|
||||
|
||||
if (match.indices.length > 4) {
|
||||
const moreMatchesText = document.getElementById("more-matches-text").textContent;
|
||||
output += `<span class="more-matches">${moreMatchesText}</span>`.replace("$MATCHES", `+${match.indices.length - MAX_RESULTS}`);
|
||||
}
|
||||
}
|
||||
return output + "</div>";
|
||||
}
|
||||
|
||||
/*window.addEventListener("click", function (event) {
|
||||
if (searchSetup && searchBar.getAttribute("disabled") === null && !searchContainer.contains(event.target)) {
|
||||
toggleSearch();
|
||||
}
|
||||
}, { passive: true });*/
|
||||
|
||||
document.addEventListener("keydown", function(event) {
|
||||
if (event.key === "/") {
|
||||
event.preventDefault();
|
||||
toggleSearch();
|
||||
}
|
||||
});
|
||||
|
||||
document.getElementById("search-toggle").addEventListener("click", toggleSearch);
|
||||
}
|
||||
|
||||
if (document.readyState === "complete" ||
|
||||
(document.readyState !== "loading" && !document.documentElement.doScroll))
|
||||
initSearch();
|
||||
else
|
||||
document.addEventListener("DOMContentLoaded", initSearch);
|
|
@ -1,15 +0,0 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
|
||||
<url>
|
||||
<loc>https://studio-umzu.de/</loc>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://studio-umzu.de/de/</loc>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://studio-umzu.de/de/tags/</loc>
|
||||
</url>
|
||||
<url>
|
||||
<loc>https://studio-umzu.de/tags/</loc>
|
||||
</url>
|
||||
</urlset>
|
|
@ -1,283 +0,0 @@
|
|||
/*
|
||||
* theme "Solarized (dark)" generated by syntect
|
||||
*/
|
||||
|
||||
.z-code {
|
||||
color: #839496;
|
||||
background-color: #002b36;
|
||||
}
|
||||
|
||||
.z-comment, .z-meta.z-documentation {
|
||||
color: #586e75;
|
||||
}
|
||||
.z-string {
|
||||
color: #2aa198;
|
||||
}
|
||||
.z-string.z-regexp {
|
||||
color: #2aa198;
|
||||
}
|
||||
.z-constant.z-character.z-escape {
|
||||
color: #dc322f;
|
||||
}
|
||||
.z-constant.z-numeric {
|
||||
color: #6c71c4;
|
||||
}
|
||||
.z-variable {
|
||||
color: #268bd2;
|
||||
}
|
||||
.z-variable.z-function {
|
||||
color: #b58900;
|
||||
}
|
||||
.z-variable.z-language {
|
||||
color: #d33682;
|
||||
}
|
||||
.z-keyword {
|
||||
color: #859900;
|
||||
}
|
||||
.z-meta.z-import .z-keyword, .z-keyword.z-control.z-import, .z-keyword.z-control.z-import.z-from, .z-keyword.z-other.z-import, .z-keyword.z-control.z-at-rule.z-include, .z-keyword.z-control.z-at-rule.z-import {
|
||||
color: #cb4b16;
|
||||
}
|
||||
.z-keyword.z-operator.z-comparison, .z-keyword.z-operator.z-assignment, .z-keyword.z-operator.z-arithmetic {
|
||||
color: #657b83;
|
||||
}
|
||||
.z-storage {
|
||||
color: #859900;
|
||||
}
|
||||
.z-storage.z-modifier {
|
||||
color: #93a1a1;
|
||||
}
|
||||
.z-keyword.z-control.z-class, .z-entity.z-name, .z-entity.z-name.z-class, .z-entity.z-name.z-type.z-class {
|
||||
color: #b58900;
|
||||
}
|
||||
.z-entity.z-other.z-inherited-class {
|
||||
color: #268bd2;
|
||||
}
|
||||
.z-entity.z-other.z-attribute-name {
|
||||
color: #b58900;
|
||||
}
|
||||
.z-support, .z-support.z-type, .z-support.z-class {
|
||||
color: #859900;
|
||||
}
|
||||
.z-entity.z-name.z-function {
|
||||
color: #b58900;
|
||||
}
|
||||
.z-punctuation.z-definition.z-variable {
|
||||
color: #859900;
|
||||
}
|
||||
.z-constant, .z-constant.z-language, .z-meta.z-preprocessor {
|
||||
color: #b58900;
|
||||
}
|
||||
.z-entity.z-name.z-section {
|
||||
color: #cb4b16;
|
||||
}
|
||||
.z-support.z-function.z-construct, .z-keyword.z-other.z-new {
|
||||
color: #dc322f;
|
||||
}
|
||||
.z-constant.z-character, .z-constant.z-other {
|
||||
color: #cb4b16;
|
||||
}
|
||||
.z-entity.z-name.z-tag {
|
||||
color: #268bd2;
|
||||
}
|
||||
.z-punctuation.z-definition.z-tag.z-html, .z-punctuation.z-definition.z-tag.z-begin, .z-punctuation.z-definition.z-tag.z-end {
|
||||
color: #586e75;
|
||||
}
|
||||
.z-support.z-function {
|
||||
color: #859900;
|
||||
}
|
||||
.z-punctuation.z-separator.z-continuation {
|
||||
color: #dc322f;
|
||||
}
|
||||
.z-storage.z-type {
|
||||
color: #268bd2;
|
||||
}
|
||||
.z-support.z-type.z-exception {
|
||||
color: #cb4b16;
|
||||
}
|
||||
.z-keyword.z-other.z-special-method {
|
||||
color: #cb4b16;
|
||||
}
|
||||
.z-invalid {
|
||||
background-color: #6e2e32;
|
||||
}
|
||||
.z-string.z-quoted.z-double, .z-string.z-quoted.z-single {
|
||||
color: #2aa198;
|
||||
}
|
||||
.z-punctuation.z-definition.z-string {
|
||||
color: #839496;
|
||||
}
|
||||
.z-meta.z-brace.z-square, .z-punctuation.z-section.z-brackets {
|
||||
color: #268bd2;
|
||||
}
|
||||
.z-meta.z-brace.z-round, .z-meta.z-brace.z-curly, .z-punctuation.z-section, .z-punctuation.z-section.z-block, .z-punctuation.z-definition.z-parameters, .z-punctuation.z-section.z-group {
|
||||
color: #657b83;
|
||||
}
|
||||
.z-support.z-constant.z-color, .z-invalid.z-deprecated.z-color.z-w3c-non-standard-color-name.z-scss {
|
||||
color: #b58900;
|
||||
}
|
||||
.z-meta.z-selector.z-css {
|
||||
color: #657b83;
|
||||
}
|
||||
.z-entity.z-name.z-tag.z-css, .z-entity.z-name.z-tag.z-scss, .z-source.z-less .z-keyword.z-control.z-html.z-elements, .z-source.z-sass .z-keyword.z-control.z-untitled {
|
||||
color: #b58900;
|
||||
}
|
||||
.z-entity.z-other.z-attribute-name.z-class {
|
||||
color: #b58900;
|
||||
}
|
||||
.z-entity.z-other.z-attribute-name.z-id {
|
||||
color: #b58900;
|
||||
}
|
||||
.z-entity.z-other.z-attribute-name.z-pseudo-element, .z-entity.z-other.z-attribute-name.z-tag.z-pseudo-element, .z-entity.z-other.z-attribute-name.z-pseudo-class, .z-entity.z-other.z-attribute-name.z-tag.z-pseudo-class {
|
||||
color: #268bd2;
|
||||
}
|
||||
.z-text.z-html.z-basic .z-meta.z-tag.z-other.z-html, .z-text.z-html.z-basic .z-meta.z-tag.z-any.z-html, .z-text.z-html.z-basic .z-meta.z-tag.z-block.z-any, .z-text.z-html.z-basic .z-meta.z-tag.z-inline.z-any, .z-text.z-html.z-basic .z-meta.z-tag.z-structure.z-any.z-html, .z-text.z-html.z-basic .z-source.z-js.z-embedded.z-html, .z-punctuation.z-separator.z-key-value.z-html {
|
||||
color: #657b83;
|
||||
}
|
||||
.z-text.z-html.z-basic .z-entity.z-other.z-attribute-name.z-html, .z-meta.z-tag.z-xml .z-entity.z-other.z-attribute-name {
|
||||
color: #b58900;
|
||||
}
|
||||
.z-keyword.z-other.z-special-method.z-ruby {
|
||||
color: #859900;
|
||||
}
|
||||
.z-variable.z-other.z-constant.z-ruby {
|
||||
color: #b58900;
|
||||
}
|
||||
.z-constant.z-other.z-symbol.z-ruby {
|
||||
color: #2aa198;
|
||||
}
|
||||
.z-keyword.z-other.z-special-method.z-ruby {
|
||||
color: #cb4b16;
|
||||
}
|
||||
.z-meta.z-array .z-support.z-function.z-construct.z-php {
|
||||
color: #b58900;
|
||||
}
|
||||
.z-entity.z-name.z-function.z-preprocessor.z-c, .z-meta.z-preprocessor.z-c.z-include, .z-meta.z-preprocessor.z-macro.z-c {
|
||||
color: #cb4b16;
|
||||
}
|
||||
.z-meta.z-preprocessor.z-c.z-include .z-string.z-quoted.z-other.z-lt-gt.z-include.z-c, .z-meta.z-preprocessor.z-c.z-include .z-punctuation.z-definition.z-string.z-begin.z-c, .z-meta.z-preprocessor.z-c.z-include .z-punctuation.z-definition.z-string.z-end.z-c {
|
||||
color: #2aa198;
|
||||
}
|
||||
.z-other.z-package.z-exclude, .z-other.z-remove {
|
||||
color: #dc322f;
|
||||
}
|
||||
.z-other.z-add {
|
||||
color: #2aa198;
|
||||
}
|
||||
.z-punctuation.z-section.z-group.z-tex, .z-punctuation.z-definition.z-arguments.z-begin.z-latex, .z-punctuation.z-definition.z-arguments.z-end.z-latex, .z-punctuation.z-definition.z-arguments.z-latex {
|
||||
color: #dc322f;
|
||||
}
|
||||
.z-meta.z-group.z-braces.z-tex {
|
||||
color: #b58900;
|
||||
}
|
||||
.z-string.z-other.z-math.z-tex {
|
||||
color: #b58900;
|
||||
}
|
||||
.z-variable.z-parameter.z-function.z-latex {
|
||||
color: #cb4b16;
|
||||
}
|
||||
.z-punctuation.z-definition.z-constant.z-math.z-tex {
|
||||
color: #dc322f;
|
||||
}
|
||||
.z-text.z-tex.z-latex .z-constant.z-other.z-math.z-tex, .z-constant.z-other.z-general.z-math.z-tex, .z-constant.z-other.z-general.z-math.z-tex, .z-constant.z-character.z-math.z-tex {
|
||||
color: #2aa198;
|
||||
}
|
||||
.z-string.z-other.z-math.z-tex {
|
||||
color: #b58900;
|
||||
}
|
||||
.z-punctuation.z-definition.z-string.z-begin.z-tex, .z-punctuation.z-definition.z-string.z-end.z-tex {
|
||||
color: #dc322f;
|
||||
}
|
||||
.z-keyword.z-control.z-label.z-latex, .z-text.z-tex.z-latex .z-constant.z-other.z-general.z-math.z-tex {
|
||||
color: #2aa198;
|
||||
}
|
||||
.z-variable.z-parameter.z-definition.z-label.z-latex {
|
||||
color: #dc322f;
|
||||
}
|
||||
.z-support.z-function.z-be.z-latex {
|
||||
color: #859900;
|
||||
}
|
||||
.z-support.z-function.z-section.z-latex {
|
||||
color: #cb4b16;
|
||||
}
|
||||
.z-support.z-function.z-general.z-tex {
|
||||
color: #2aa198;
|
||||
}
|
||||
.z-keyword.z-control.z-ref.z-latex {
|
||||
color: #2aa198;
|
||||
}
|
||||
.z-storage.z-type.z-class.z-python, .z-storage.z-type.z-function.z-python, .z-storage.z-modifier.z-global.z-python {
|
||||
color: #859900;
|
||||
}
|
||||
.z-support.z-type.z-exception.z-python {
|
||||
color: #b58900;
|
||||
}
|
||||
.z-meta.z-scope.z-for-in-loop.z-shell, .z-variable.z-other.z-loop.z-shell {
|
||||
color: #93a1a1;
|
||||
}
|
||||
.z-meta.z-scope.z-case-block.z-shell, .z-meta.z-scope.z-case-body.z-shell {
|
||||
color: #93a1a1;
|
||||
}
|
||||
.z-punctuation.z-definition.z-logical-expression.z-shell {
|
||||
color: #dc322f;
|
||||
}
|
||||
.z-storage.z-modifier.z-c++ {
|
||||
color: #859900;
|
||||
}
|
||||
.z-support.z-function.z-perl {
|
||||
color: #268bd2;
|
||||
}
|
||||
.z-meta.z-diff, .z-meta.z-diff.z-header {
|
||||
color: #586e75;
|
||||
}
|
||||
.z-meta.z-diff.z-range {
|
||||
color: #268bd2;
|
||||
}
|
||||
.z-markup.z-deleted {
|
||||
color: #dc322f;
|
||||
}
|
||||
.z-markup.z-changed {
|
||||
color: #b58900;
|
||||
}
|
||||
.z-markup.z-inserted {
|
||||
color: #859900;
|
||||
}
|
||||
.z-markup.z-warning {
|
||||
color: #b58900;
|
||||
}
|
||||
.z-markup.z-error {
|
||||
color: #dc322f;
|
||||
}
|
||||
.z-markup.z-heading, .z-punctuation.z-definition.z-heading.z-markdown {
|
||||
color: #b58900;
|
||||
font-weight: bold;
|
||||
}
|
||||
.z-markup.z-quote {
|
||||
color: #859900;
|
||||
}
|
||||
.z-markup.z-italic {
|
||||
font-style: italic;
|
||||
}
|
||||
.z-markup.z-bold {
|
||||
font-weight: bold;
|
||||
}
|
||||
.z-markup.z-underline.z-link.z-markdown, .z-meta.z-link.z-reference .z-constant.z-other.z-reference.z-link.z-markdown {
|
||||
color: #2aa198;
|
||||
}
|
||||
.z-constant.z-other.z-reference.z-link.z-markdown {
|
||||
color: #6c71c4;
|
||||
}
|
||||
.z-meta.z-paragraph.z-markdown .z-meta.z-dummy.z-line-break {
|
||||
background-color: #586e75;
|
||||
}
|
||||
.z-brackethighlighter.z-all {
|
||||
color: #586e75;
|
||||
}
|
||||
.z-entity.z-name.z-filename.z-find-in-files {
|
||||
color: #2aa198;
|
||||
}
|
||||
.z-constant.z-numeric.z-line-number.z-find-in-files {
|
||||
color: #586e75;
|
||||
}
|
||||
.z-variable.z-other.z-readwrite.z-js, .z-variable.z-other.z-object.z-js, .z-variable.z-other.z-constant.z-js {
|
||||
color: #839496;
|
||||
}
|
|
@ -1,283 +0,0 @@
|
|||
/*
|
||||
* theme "Solarized (light)" generated by syntect
|
||||
*/
|
||||
|
||||
.z-code {
|
||||
color: #657b83;
|
||||
background-color: #fdf6e3;
|
||||
}
|
||||
|
||||
.z-comment, .z-meta.z-documentation {
|
||||
color: #93a1a1;
|
||||
}
|
||||
.z-string {
|
||||
color: #2aa198;
|
||||
}
|
||||
.z-string.z-regexp {
|
||||
color: #2aa198;
|
||||
}
|
||||
.z-constant.z-character.z-escape {
|
||||
color: #dc322f;
|
||||
}
|
||||
.z-constant.z-numeric {
|
||||
color: #6c71c4;
|
||||
}
|
||||
.z-variable {
|
||||
color: #268bd2;
|
||||
}
|
||||
.z-variable.z-function {
|
||||
color: #b58900;
|
||||
}
|
||||
.z-variable.z-language {
|
||||
color: #d33682;
|
||||
}
|
||||
.z-keyword {
|
||||
color: #859900;
|
||||
}
|
||||
.z-meta.z-import .z-keyword, .z-keyword.z-control.z-import, .z-keyword.z-control.z-import.z-from, .z-keyword.z-other.z-import, .z-keyword.z-control.z-at-rule.z-include, .z-keyword.z-control.z-at-rule.z-import {
|
||||
color: #cb4b16;
|
||||
}
|
||||
.z-keyword.z-operator.z-comparison, .z-keyword.z-operator.z-assignment, .z-keyword.z-operator.z-arithmetic {
|
||||
color: #657b83;
|
||||
}
|
||||
.z-storage {
|
||||
color: #859900;
|
||||
}
|
||||
.z-storage.z-modifier {
|
||||
color: #586e75;
|
||||
}
|
||||
.z-keyword.z-control.z-class, .z-entity.z-name, .z-entity.z-name.z-class, .z-entity.z-name.z-type.z-class {
|
||||
color: #b58900;
|
||||
}
|
||||
.z-entity.z-other.z-inherited-class {
|
||||
color: #268bd2;
|
||||
}
|
||||
.z-entity.z-other.z-attribute-name {
|
||||
color: #b58900;
|
||||
}
|
||||
.z-support, .z-support.z-type, .z-support.z-class {
|
||||
color: #859900;
|
||||
}
|
||||
.z-entity.z-name.z-function {
|
||||
color: #b58900;
|
||||
}
|
||||
.z-punctuation.z-definition.z-variable {
|
||||
color: #859900;
|
||||
}
|
||||
.z-constant, .z-constant.z-language, .z-meta.z-preprocessor {
|
||||
color: #b58900;
|
||||
}
|
||||
.z-entity.z-name.z-section {
|
||||
color: #cb4b16;
|
||||
}
|
||||
.z-support.z-function.z-construct, .z-keyword.z-other.z-new {
|
||||
color: #dc322f;
|
||||
}
|
||||
.z-constant.z-character, .z-constant.z-other {
|
||||
color: #cb4b16;
|
||||
}
|
||||
.z-entity.z-name.z-tag {
|
||||
color: #268bd2;
|
||||
}
|
||||
.z-punctuation.z-definition.z-tag.z-html, .z-punctuation.z-definition.z-tag.z-begin, .z-punctuation.z-definition.z-tag.z-end {
|
||||
color: #93a1a1;
|
||||
}
|
||||
.z-support.z-function {
|
||||
color: #859900;
|
||||
}
|
||||
.z-punctuation.z-separator.z-continuation {
|
||||
color: #dc322f;
|
||||
}
|
||||
.z-storage.z-type {
|
||||
color: #268bd2;
|
||||
}
|
||||
.z-support.z-type.z-exception {
|
||||
color: #cb4b16;
|
||||
}
|
||||
.z-keyword.z-other.z-special-method {
|
||||
color: #cb4b16;
|
||||
}
|
||||
.z-invalid {
|
||||
background-color: #ec9489;
|
||||
}
|
||||
.z-string.z-quoted.z-double, .z-string.z-quoted.z-single {
|
||||
color: #2aa198;
|
||||
}
|
||||
.z-punctuation.z-definition.z-string {
|
||||
color: #839496;
|
||||
}
|
||||
.z-meta.z-brace.z-square, .z-punctuation.z-section.z-brackets {
|
||||
color: #268bd2;
|
||||
}
|
||||
.z-meta.z-brace.z-round, .z-meta.z-brace.z-curly, .z-punctuation.z-section, .z-punctuation.z-section.z-block, .z-punctuation.z-definition.z-parameters, .z-punctuation.z-section.z-group {
|
||||
color: #657b83;
|
||||
}
|
||||
.z-support.z-constant.z-color, .z-invalid.z-deprecated.z-color.z-w3c-non-standard-color-name.z-scss {
|
||||
color: #b58900;
|
||||
}
|
||||
.z-meta.z-selector.z-css {
|
||||
color: #657b83;
|
||||
}
|
||||
.z-entity.z-name.z-tag.z-css, .z-entity.z-name.z-tag.z-scss, .z-source.z-less .z-keyword.z-control.z-html.z-elements, .z-source.z-sass .z-keyword.z-control.z-untitled {
|
||||
color: #b58900;
|
||||
}
|
||||
.z-entity.z-other.z-attribute-name.z-class {
|
||||
color: #b58900;
|
||||
}
|
||||
.z-entity.z-other.z-attribute-name.z-id {
|
||||
color: #b58900;
|
||||
}
|
||||
.z-entity.z-other.z-attribute-name.z-pseudo-element, .z-entity.z-other.z-attribute-name.z-tag.z-pseudo-element, .z-entity.z-other.z-attribute-name.z-pseudo-class, .z-entity.z-other.z-attribute-name.z-tag.z-pseudo-class {
|
||||
color: #268bd2;
|
||||
}
|
||||
.z-text.z-html.z-basic .z-meta.z-tag.z-other.z-html, .z-text.z-html.z-basic .z-meta.z-tag.z-any.z-html, .z-text.z-html.z-basic .z-meta.z-tag.z-block.z-any, .z-text.z-html.z-basic .z-meta.z-tag.z-inline.z-any, .z-text.z-html.z-basic .z-meta.z-tag.z-structure.z-any.z-html, .z-text.z-html.z-basic .z-source.z-js.z-embedded.z-html, .z-punctuation.z-separator.z-key-value.z-html {
|
||||
color: #657b83;
|
||||
}
|
||||
.z-text.z-html.z-basic .z-entity.z-other.z-attribute-name.z-html, .z-meta.z-tag.z-xml .z-entity.z-other.z-attribute-name {
|
||||
color: #b58900;
|
||||
}
|
||||
.z-keyword.z-other.z-special-method.z-ruby {
|
||||
color: #859900;
|
||||
}
|
||||
.z-variable.z-other.z-constant.z-ruby {
|
||||
color: #b58900;
|
||||
}
|
||||
.z-constant.z-other.z-symbol.z-ruby {
|
||||
color: #2aa198;
|
||||
}
|
||||
.z-keyword.z-other.z-special-method.z-ruby {
|
||||
color: #cb4b16;
|
||||
}
|
||||
.z-meta.z-array .z-support.z-function.z-construct.z-php {
|
||||
color: #b58900;
|
||||
}
|
||||
.z-entity.z-name.z-function.z-preprocessor.z-c, .z-meta.z-preprocessor.z-c.z-include, .z-meta.z-preprocessor.z-macro.z-c {
|
||||
color: #cb4b16;
|
||||
}
|
||||
.z-meta.z-preprocessor.z-c.z-include .z-string.z-quoted.z-other.z-lt-gt.z-include.z-c, .z-meta.z-preprocessor.z-c.z-include .z-punctuation.z-definition.z-string.z-begin.z-c, .z-meta.z-preprocessor.z-c.z-include .z-punctuation.z-definition.z-string.z-end.z-c {
|
||||
color: #2aa198;
|
||||
}
|
||||
.z-other.z-package.z-exclude, .z-other.z-remove {
|
||||
color: #dc322f;
|
||||
}
|
||||
.z-other.z-add {
|
||||
color: #2aa198;
|
||||
}
|
||||
.z-punctuation.z-section.z-group.z-tex, .z-punctuation.z-definition.z-arguments.z-begin.z-latex, .z-punctuation.z-definition.z-arguments.z-end.z-latex, .z-punctuation.z-definition.z-arguments.z-latex {
|
||||
color: #dc322f;
|
||||
}
|
||||
.z-meta.z-group.z-braces.z-tex {
|
||||
color: #b58900;
|
||||
}
|
||||
.z-string.z-other.z-math.z-tex {
|
||||
color: #b58900;
|
||||
}
|
||||
.z-variable.z-parameter.z-function.z-latex {
|
||||
color: #cb4b16;
|
||||
}
|
||||
.z-punctuation.z-definition.z-constant.z-math.z-tex {
|
||||
color: #dc322f;
|
||||
}
|
||||
.z-text.z-tex.z-latex .z-constant.z-other.z-math.z-tex, .z-constant.z-other.z-general.z-math.z-tex, .z-constant.z-other.z-general.z-math.z-tex, .z-constant.z-character.z-math.z-tex {
|
||||
color: #2aa198;
|
||||
}
|
||||
.z-string.z-other.z-math.z-tex {
|
||||
color: #b58900;
|
||||
}
|
||||
.z-punctuation.z-definition.z-string.z-begin.z-tex, .z-punctuation.z-definition.z-string.z-end.z-tex {
|
||||
color: #dc322f;
|
||||
}
|
||||
.z-keyword.z-control.z-label.z-latex, .z-text.z-tex.z-latex .z-constant.z-other.z-general.z-math.z-tex {
|
||||
color: #2aa198;
|
||||
}
|
||||
.z-variable.z-parameter.z-definition.z-label.z-latex {
|
||||
color: #dc322f;
|
||||
}
|
||||
.z-support.z-function.z-be.z-latex {
|
||||
color: #859900;
|
||||
}
|
||||
.z-support.z-function.z-section.z-latex {
|
||||
color: #cb4b16;
|
||||
}
|
||||
.z-support.z-function.z-general.z-tex {
|
||||
color: #2aa198;
|
||||
}
|
||||
.z-keyword.z-control.z-ref.z-latex {
|
||||
color: #2aa198;
|
||||
}
|
||||
.z-storage.z-type.z-class.z-python, .z-storage.z-type.z-function.z-python, .z-storage.z-modifier.z-global.z-python {
|
||||
color: #859900;
|
||||
}
|
||||
.z-support.z-type.z-exception.z-python {
|
||||
color: #b58900;
|
||||
}
|
||||
.z-meta.z-scope.z-for-in-loop.z-shell, .z-variable.z-other.z-loop.z-shell {
|
||||
color: #586e75;
|
||||
}
|
||||
.z-meta.z-scope.z-case-block.z-shell, .z-meta.z-scope.z-case-body.z-shell {
|
||||
color: #586e75;
|
||||
}
|
||||
.z-punctuation.z-definition.z-logical-expression.z-shell {
|
||||
color: #dc322f;
|
||||
}
|
||||
.z-storage.z-modifier.z-c++ {
|
||||
color: #859900;
|
||||
}
|
||||
.z-support.z-function.z-perl {
|
||||
color: #268bd2;
|
||||
}
|
||||
.z-meta.z-diff, .z-meta.z-diff.z-header {
|
||||
color: #93a1a1;
|
||||
}
|
||||
.z-meta.z-diff.z-range {
|
||||
color: #268bd2;
|
||||
}
|
||||
.z-markup.z-deleted {
|
||||
color: #dc322f;
|
||||
}
|
||||
.z-markup.z-changed {
|
||||
color: #b58900;
|
||||
}
|
||||
.z-markup.z-inserted {
|
||||
color: #859900;
|
||||
}
|
||||
.z-markup.z-warning {
|
||||
color: #b58900;
|
||||
}
|
||||
.z-markup.z-error {
|
||||
color: #dc322f;
|
||||
}
|
||||
.z-markup.z-heading, .z-punctuation.z-definition.z-heading.z-markdown {
|
||||
color: #b58900;
|
||||
font-weight: bold;
|
||||
}
|
||||
.z-markup.z-quote {
|
||||
color: #859900;
|
||||
}
|
||||
.z-markup.z-italic {
|
||||
font-style: italic;
|
||||
}
|
||||
.z-markup.z-bold {
|
||||
font-weight: bold;
|
||||
}
|
||||
.z-markup.z-underline.z-link.z-markdown, .z-meta.z-link.z-reference .z-constant.z-other.z-reference.z-link.z-markdown {
|
||||
color: #2aa198;
|
||||
}
|
||||
.z-constant.z-other.z-reference.z-link.z-markdown {
|
||||
color: #6c71c4;
|
||||
}
|
||||
.z-meta.z-paragraph.z-markdown .z-meta.z-dummy.z-line-break {
|
||||
background-color: #eee8d5;
|
||||
}
|
||||
.z-brackethighlighter.z-all {
|
||||
color: #93a1a1;
|
||||
}
|
||||
.z-entity.z-name.z-filename.z-find-in-files {
|
||||
color: #2aa198;
|
||||
}
|
||||
.z-constant.z-numeric.z-line-number.z-find-in-files {
|
||||
color: #93a1a1;
|
||||
}
|
||||
.z-variable.z-other.z-readwrite.z-js, .z-variable.z-other.z-object.z-js, .z-variable.z-other.z-constant.z-js {
|
||||
color: #657b83;
|
||||
}
|
|
@ -1,104 +0,0 @@
|
|||
// Theme Initialization
|
||||
(function () {
|
||||
// Get the default theme from the HTML data-theme attribute.
|
||||
const defaultTheme = document.documentElement.getAttribute("data-theme");
|
||||
|
||||
// Set the data-default-theme attribute only if defaultTheme is not null.
|
||||
if (defaultTheme) {
|
||||
document.documentElement.setAttribute("data-default-theme", defaultTheme);
|
||||
}
|
||||
|
||||
// Attempt to retrieve the current theme from the browser's local storage.
|
||||
const storedTheme = localStorage.getItem("theme");
|
||||
|
||||
if (storedTheme && storedTheme !== "system") {
|
||||
document.documentElement.setAttribute("data-theme", storedTheme);
|
||||
} else if (defaultTheme && storedTheme !== "system") {
|
||||
document.documentElement.setAttribute("data-theme", defaultTheme);
|
||||
} else {
|
||||
// If no theme is found in local storage and no default theme is set, hand over control to the CSS.
|
||||
document.documentElement.removeAttribute("data-theme");
|
||||
}
|
||||
|
||||
// Expose defaultTheme to the outer scope.
|
||||
window.defaultTheme = defaultTheme;
|
||||
})();
|
||||
|
||||
// Icon Update and Theme Switching
|
||||
function setTheme(theme, saveToLocalStorage = false) {
|
||||
if (theme === "system") {
|
||||
document.documentElement.removeAttribute("data-theme");
|
||||
} else {
|
||||
document.documentElement.setAttribute("data-theme", theme);
|
||||
}
|
||||
|
||||
if (saveToLocalStorage) {
|
||||
localStorage.setItem("theme", theme);
|
||||
} else {
|
||||
localStorage.removeItem("theme");
|
||||
}
|
||||
|
||||
// Update icon class based on the selected theme.
|
||||
updateIconClass(theme);
|
||||
|
||||
// Update the active button based on the selected theme.
|
||||
updateActiveButton(theme);
|
||||
}
|
||||
|
||||
function resetTheme() {
|
||||
// Reset the theme to the default or system preference if no default is set.
|
||||
setTheme(window.defaultTheme || "system");
|
||||
}
|
||||
|
||||
function switchTheme(theme) {
|
||||
if (theme === "system") {
|
||||
resetTheme();
|
||||
} else {
|
||||
setTheme(theme, true);
|
||||
}
|
||||
}
|
||||
|
||||
function updateIconClass(theme) {
|
||||
const iconElement = document.querySelector("#theme-switcher summary .icon");
|
||||
|
||||
// Remove any existing theme classes
|
||||
iconElement.classList.remove("light", "dark");
|
||||
|
||||
// Add the appropriate class based on the selected theme
|
||||
if (theme === "light") {
|
||||
iconElement.classList.add("light");
|
||||
} else if (theme === "dark") {
|
||||
iconElement.classList.add("dark");
|
||||
}
|
||||
}
|
||||
|
||||
function updateActiveButton(theme) {
|
||||
// Remove .active class from all buttons
|
||||
document.querySelectorAll('#theme-switcher button').forEach(button => {
|
||||
button.classList.remove('active');
|
||||
});
|
||||
|
||||
// Add .active class to the button corresponding to the current theme
|
||||
const activeButton = document.querySelector(`#theme-${theme}`);
|
||||
if (activeButton) {
|
||||
activeButton.classList.add('active');
|
||||
}
|
||||
}
|
||||
|
||||
document.getElementById("theme-light").addEventListener("click", function () {
|
||||
switchTheme("light");
|
||||
});
|
||||
document.getElementById("theme-dark").addEventListener("click", function () {
|
||||
switchTheme("dark");
|
||||
});
|
||||
document.getElementById("theme-system").addEventListener("click", function () {
|
||||
switchTheme("system");
|
||||
});
|
||||
|
||||
// Update icon class on page load based on current theme
|
||||
const currentTheme = localStorage.getItem("theme") || window.defaultTheme || "system";
|
||||
updateIconClass(currentTheme);
|
||||
updateActiveButton(currentTheme);
|
||||
|
||||
// Make the switchTheme function accessible globally
|
||||
window.switchTheme = switchTheme;
|
BIN
static/images/colleagues/aron_petau.jpeg
Normal file
After Width: | Height: | Size: 183 KiB |
BIN
static/images/colleagues/friedrich_weber.jpg
Normal file
After Width: | Height: | Size: 69 KiB |