Compare commits
2 commits
d38c8faa30
...
41ace4dad8
Author | SHA1 | Date | |
---|---|---|---|
41ace4dad8 | |||
0a6b3f0128 |
20
config.toml
|
@ -40,8 +40,8 @@ styles = [
|
||||||
bundled_fonts = false
|
bundled_fonts = false
|
||||||
issues_url = "https://forgejo.petau.net/aron/studio-umzu/issues"
|
issues_url = "https://forgejo.petau.net/aron/studio-umzu/issues"
|
||||||
source_url = "https://forgejo.petau.net/aron/studio-umzu"
|
source_url = "https://forgejo.petau.net/aron/studio-umzu"
|
||||||
default_theme = "dark"
|
default_theme = "light"
|
||||||
accent_color = "#b12633"
|
accent_color = "#ff0000"
|
||||||
accent_color_dark = "#c54854"
|
accent_color_dark = "#c54854"
|
||||||
toc = true
|
toc = true
|
||||||
toc_sidebar = true
|
toc_sidebar = true
|
||||||
|
@ -61,22 +61,16 @@ show_feed = true
|
||||||
show_theme_switcher = true
|
show_theme_switcher = true
|
||||||
show_repo = true
|
show_repo = true
|
||||||
links = [
|
links = [
|
||||||
{ url = "https://friedrichwebergoizel.com", name = "About Friedrich" },
|
{ url = "https://friedrichwebergoizel.com", name = "Friedrich", external = true },
|
||||||
{ url = "https://aron.petau.net", name = "About Aron" },
|
{ url = "https://aron.petau.net", name = "Aron", external = true },
|
||||||
|
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[extra.footer]
|
[extra.footer]
|
||||||
links = [
|
|
||||||
{ url = "https://friedrichwebergoizel.com", name = "About Friedrich" },
|
|
||||||
{ url = "https://aron.petau.net", name = "About Aron" },
|
|
||||||
|
|
||||||
]
|
|
||||||
|
|
||||||
socials = [
|
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 = "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" }
|
||||||
{ url = "mailto:aron@petau.net,f.goizel@yahoo.com?subject=[Workshop]", name = "Mail", 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.5zm0 1.5v.243l10.5 7.006 10.5-7.006V6zm21 12V8.132l-10.038 6.697a.75.75 0 0 1-.924 0L1.5 8.132V18z'/%3E%3C/svg%3E" },
|
|
||||||
|
|
||||||
]
|
]
|
||||||
show_copyright = true
|
show_copyright = true
|
||||||
show_powered_by = false
|
show_powered_by = false
|
||||||
|
|
|
@ -1,49 +1,99 @@
|
||||||
+++
|
+++
|
||||||
title = "Studio UMZU"
|
title = "Werkraum - Making Workshops"
|
||||||
description = "Die Zukunft gestalten — mit Händen, Köpfen und Code. Buchen Sie uns für Ihren nächsten digitalen / handwerklichen Workshop"
|
description = "Die Zukunft gestalten — mit Händen, Köpfen und Code. Buchen Sie uns für Ihren nächsten Digital- oder Handwerksworkshop."
|
||||||
|
draft=false
|
||||||
|
|
||||||
[extra]
|
[extra]
|
||||||
|
show_copyright = false
|
||||||
show_shares = true
|
show_shares = true
|
||||||
show_source = false
|
show_source = false
|
||||||
show_toc = true
|
show_toc = true
|
||||||
inline_toc = true
|
inline_toc = true
|
||||||
|
|
||||||
|
[extra.footer]
|
||||||
|
copyright = "© Test"
|
||||||
|
show_copyright = false
|
||||||
+++
|
+++
|
||||||
|
|
||||||
|
{% alert(note=true) %}
|
||||||
|
Dies ist ein Work in Progress.
|
||||||
|
Die hier bereitgestellten Informationen können sich noch ändern.
|
||||||
|
{% end %}
|
||||||
|
|
||||||
## Euer Kreativ-Workshop-Team
|
## Euer Kreativ-Workshop-Team
|
||||||
|
|
||||||
<aside>
|
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.
|
||||||
|
|
||||||
</aside>
|
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.
|
||||||
|
Jeder Workshop wird individuell auf eure Bedürfnisse, euer Publikum und euren Raum zugeschnitten.
|
||||||
|
|
||||||
Wir sind Studio UMZU – Aron Petau und Friedrich Weber Goizel — Maker, Pädagogen und leidenschaftliche Tüftler, die in Berlin Workshops konzipieren und umsetzen.
|
- Workshops zu 3D-Druck, Lasercutting, Plotten, Robotik und 3D-Design
|
||||||
|
- Flexible Durchführung: auf eurem Equipment oder mit unseren mobilen Demo-Setups
|
||||||
|
- Erfahrung mit Schulklassen, Bibliotheken und öffentlichem Publikum
|
||||||
|
- Maßgeschneiderte Workshop-Konzepte passend zu euren Zielen und Teilnehmenden
|
||||||
|
- Wir helfen euch sogar bei der Planung, Gestaltung und dem Aufbau neuer Makerspaces!
|
||||||
|
|
||||||
Wir bringen die Welt des Machens in Bibliotheken, Schulen und Jugendzentren und bieten praktische Workshops, die Kreativität, Neugier und technisches Können fördern.
|
Lasst uns gemeinsam einen Raum schaffen, in dem Handwerk auf Code, Analoges auf Digitales und Ideen auf Leben treffen.
|
||||||
|
Ihr könnt uns für einmalige Veranstaltungen oder laufende Programme kontaktieren.
|
||||||
Ob Sie bereits einen Makerspace mit 3D-Druckern, Lasercuttern oder Plottern haben oder gerade erst anfangen – wir passen uns an.
|
|
||||||
Wir bieten sowohl mobile Vorführungen und Einführungen als auch vertiefende Workshops, die auf Ihrer vorhandenen Ausstattung aufbauen.
|
|
||||||
Jeder Workshop wird individuell auf Ihre Bedürfnisse, Zielgruppen und Räume zugeschnitten.
|
|
||||||
|
|
||||||
- Workshops zu 3D-Druck, Lasercutting, Plotten, Robotik und 3D-Design
|
|
||||||
- Flexible Durchführung: auf Ihrer Ausstattung oder mit unseren mobilen Demo-Setups
|
|
||||||
- Erfahrung mit Schulklassen, Bibliotheken und öffentlichem Publikum
|
|
||||||
- Individuelle Workshop-Konzepte passend zu Ihren Zielen und Teilnehmenden
|
|
||||||
- Wir helfen sogar beim Entwerfen, Kuratieren und Aufbau neuer Makerspaces!
|
|
||||||
|
|
||||||
Lasst uns gemeinsam Räume schaffen, in denen Handwerk auf Code trifft, Analoges auf Digitales und Ideen lebendig werden.
|
|
||||||
Wir helfen gerne dabei, euren Ort in einen Knotenpunkt für Kreativität und Lernen zu verwandeln.
|
|
||||||
Kontaktiert uns für einmalige Veranstaltungen oder langfristige Programme.
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
## Kontakt
|
## Kontakt
|
||||||
|
|
||||||
Wir freuen uns, von euch zu hören!
|
Wir freuen uns, von euch zu hören!
|
||||||
Für Anfragen, Buchungen oder zur Besprechung individueller Workshop-Konzepte erreicht ihr uns per E-Mail:
|
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")
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
|
## Unsere Profile
|
||||||
|
|
||||||
|
### Aron
|
||||||
|
|
||||||
|
<aside>
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
</aside>
|
||||||
|
|
||||||
|
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):
|
||||||
|
|
||||||
|
### Friedrich
|
||||||
|
|
||||||
|
<aside>
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
</aside>
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
|
||||||
|
Finde [hier](https://friedrichwebergoizel.com) mehr über Friedrich heraus.
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
@ -103,59 +153,3 @@ Für Anfragen, Buchungen oder zur Besprechung individueller Workshop-Konzepte er
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
{% end %}
|
{% end %}
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Unsere Profile
|
|
||||||
|
|
||||||
Wir sind Co-Leads in einem von Berlins neuesten und charmantesten Makerspaces, dem [studio einszwovier](https://www.gvb-berlin.de/unterricht-plus/arbeitsgemeinschaften/maker-space-studio-einszwovier/).
|
|
||||||
Kommt uns dort besuchen!
|
|
||||||
|
|
||||||
### Aron
|
|
||||||
|
|
||||||
<aside>
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
</aside>
|
|
||||||
|
|
||||||
Aron hat einen Hintergrund in Kognitionswissenschaften, KI und Mediendidaktik.
|
|
||||||
Er liebt knifflige Softwareprobleme und betrachtet Kunststoffe gerne als Material für das Machen über den 3D-Druck hinaus.
|
|
||||||
Neben Workshops mit den [Jungen Tüftler*innen, Berlin](https://junge-tueftler.de) hat Aron auch mehrjährige Erfahrung in der Konzeption und Ausstattung von Maker-Umgebungen, z. B. mit
|
|
||||||
[InKüLe](https://inkuele.de), Innovationen für die künstlerische Lehre an der UdK, aber auch mit dem [DigiLab](https://digitale-lehre.uni-osnabrueck.de/uos-digilab/) an der Universität Osnabrück.
|
|
||||||
|
|
||||||
Mehr Infos gibt’s in seiner [Bio](https://aron.petau.net/pages/cv).
|
|
||||||
|
|
||||||
### Friedrich
|
|
||||||
|
|
||||||
<aside>
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
</aside>
|
|
||||||
|
|
||||||
#### Ausbildung:
|
|
||||||
|
|
||||||
[Junge Tüftler*innen, Berlin](https://junge-tueftler.de)
|
|
||||||
|
|
||||||
2014–2015 Studium der Bildenden Kunst, Hochschule der Künste Braunschweig, Bildhauerei
|
|
||||||
|
|
||||||
2015–2019 Studium der Bildenden Kunst, Universität der Künste Berlin, Konzeptkunst und Neue Medien
|
|
||||||
|
|
||||||
2019 Master of Fine Arts
|
|
||||||
|
|
||||||
2018–2021 Studium der humanoiden 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 bei GID Berlin [Futurium, Berlin](https://futurium.de)
|
|
||||||
|
|
||||||
2022 Künstlerisches Forschungsstipendium "KuRoBi4all" (Kunst, Robotik, Bibliothek für alle); Hochschule für Wirtschaft und Recht Berlin, Stadtbibliotheken Pankow Berlin, Artspring Berlin
|
|
||||||
|
|
||||||
Mehr über Friedrich findet ihr [hier](https://friedrichwebergoizel.com).
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,24 +1,29 @@
|
||||||
+++
|
+++
|
||||||
title = "Studio UMZU"
|
title = "Werkraum - Making Workshops"
|
||||||
description = "Crafting the future — hands, minds, and code. Book us for your next digital / crafts workshop"
|
description = "Crafting the future — hands, minds, and code. Book us for your next digital / crafts workshop"
|
||||||
|
draft=false
|
||||||
|
|
||||||
[extra]
|
[extra]
|
||||||
|
show_copyright = false
|
||||||
show_shares = true
|
show_shares = true
|
||||||
show_source = false
|
show_source = false
|
||||||
show_toc = true
|
show_toc = true
|
||||||
inline_toc = true
|
inline_toc = true
|
||||||
|
[extra.footer]
|
||||||
|
copyright = "© Test"
|
||||||
|
show_copyright = false
|
||||||
|
|
||||||
|
|
||||||
+++
|
+++
|
||||||
|
|
||||||
|
{% alert(note=true) %}
|
||||||
|
This is a work in Progress.
|
||||||
|
Informations on here are subject to change.
|
||||||
|
{% end %}
|
||||||
|
|
||||||
## Your Creative Workshop Team
|
## Your Creative Workshop Team
|
||||||
|
|
||||||
<aside>
|
We are Aron Petau and Friedrich Weber Goizel — makers, educators, and passionate tinkerers conceptualizing and making workshops for a living in Berlin.
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
</aside>
|
|
||||||
|
|
||||||
We are Studio UMZU - Aron Petau and Friedrich Weber Goizel — makers, educators, and passionate tinkerers conceptualizing and making workshops for a living in Berlin.
|
|
||||||
|
|
||||||
We bring the world of making to libraries, schools, and youth centers, offering hands-on workshops designed to spark creativity, curiosity, and technical skill.
|
We bring the world of making to libraries, schools, and youth centers, offering hands-on workshops designed to spark creativity, curiosity, and technical skill.
|
||||||
|
|
||||||
|
@ -26,11 +31,11 @@ Whether you already have a makerspace with 3D printers, laser cutters, or plotte
|
||||||
We can offer both portable showcases and introductory sessions as well as deep-dive workshops that build on your existing equipment.
|
We can offer both portable showcases and introductory sessions as well as deep-dive workshops that build on your existing equipment.
|
||||||
We tailor every workshop to your needs, audience, and space.
|
We tailor every workshop to your needs, audience, and space.
|
||||||
|
|
||||||
- Workshops in 3D printing, laser cutting, plotting, robotics, and 3D design
|
- Workshops in 3D printing, laser cutting, plotting, robotics, and 3D design
|
||||||
- Flexible delivery: on your equipment or with our portable demo setups
|
- Flexible delivery: on your equipment or with our portable demo setups
|
||||||
- Experience with school groups, libraries, and public audiences
|
- Experience with school groups, libraries, and public audiences
|
||||||
- Custom workshop concepts to match your goals and participants
|
- Custom workshop concepts to match your goals and participants
|
||||||
- We even help design, curate, and build out new maker spaces!
|
- We even help design, curate, and build out new maker spaces!
|
||||||
|
|
||||||
Let’s co-create a space where craft meets code, analog meets digital, and ideas come alive.
|
Let’s co-create a space where craft meets code, analog meets digital, and ideas come alive.
|
||||||
We’d love to help turn your place into a hub of creativity and learning.
|
We’d love to help turn your place into a hub of creativity and learning.
|
||||||
|
@ -43,10 +48,61 @@ You can contact us for one-time events or ongoing programs.
|
||||||
We’d love to hear from you!
|
We’d love to hear from you!
|
||||||
For inquiries, bookings, or to discuss a custom workshop, reach out to us via email at:
|
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")
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
## Our Profiles
|
||||||
|
|
||||||
|
### Aron
|
||||||
|
|
||||||
|
<aside>
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
</aside>
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
<aside>
|
||||||
|
|
||||||
|

|
||||||
|
|
||||||
|
</aside>
|
||||||
|
|
||||||
|
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).
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
Engage more with Friedrich [here](https://friedrichwebergoizel.com).
|
||||||
|
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
|
||||||
## Our combined workshop skills
|
## Our combined workshop skills
|
||||||
|
|
||||||
{% skills() %}
|
{% skills() %}
|
||||||
|
@ -104,56 +160,3 @@ For inquiries, bookings, or to discuss a custom workshop, reach out to us via em
|
||||||
]
|
]
|
||||||
{% end %}
|
{% end %}
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Our Profiles
|
|
||||||
|
|
||||||
We are Co-Leads in one of Berlins newest and cutest Makerspaces, the [studio einszwovier](https://www.gvb-berlin.de/unterricht-plus/arbeitsgemeinschaften/maker-space-studio-einszwovier/).
|
|
||||||
Come visit us there!
|
|
||||||
|
|
||||||
### Aron
|
|
||||||
|
|
||||||
<aside>
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
</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.
|
|
||||||
Besides making Workshops with the [Junge Tüftler*innen, Berlin](https://junge-tueftler.de), Aron also has a few years of experience conceptualizing and outfitting making environments, for example with
|
|
||||||
[InKüLe](https://inkuele.de), Innovationen für die künstlerische Lehre an der UdK, but also the [DigiLab](https://digitale-lehre.uni-osnabrueck.de/uos-digilab/) at the University of Osnabrück.
|
|
||||||
|
|
||||||
Read up a full [bio](https://aron.petau.net/pages/cv) here:
|
|
||||||
|
|
||||||
### Friedrich
|
|
||||||
|
|
||||||
<aside>
|
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
</aside>
|
|
||||||
|
|
||||||
#### Education:
|
|
||||||
|
|
||||||
[Junge Tüftler*innen, Berlin](https://junge-tueftler.de)
|
|
||||||
|
|
||||||
2014-2015 Studies of Fine Arts, Hochschule der Künste Braunschweig, sculpture
|
|
||||||
|
|
||||||
2015-2019 Studies of Fine Arts, Universität der Künste Berlin, Concept and New Media
|
|
||||||
|
|
||||||
2019 Master of Fine Arts
|
|
||||||
|
|
||||||
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, Berlin](https://futurium.de)
|
|
||||||
|
|
||||||
2022 Artistic Research Scholarship "KuRoBi4all" (Art, Robotics, Library for all); Hochschule für Wirtschaft und Recht Berlin, Stadtbibliotheken Pankow Berlin, Artspring Berlin
|
|
||||||
|
|
||||||
Read up more on Friedrich [here](https://friedrichwebergoizel.com).
|
|
||||||
|
|
16
old_config.toml
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
# The URL the site will be built for
|
||||||
|
base_url = "https://studio-umzu.de"
|
||||||
|
|
||||||
|
# Whether to automatically compile all Sass files in the sass directory
|
||||||
|
compile_sass = true
|
||||||
|
|
||||||
|
# Whether to build a search index to be used later on by a JavaScript library
|
||||||
|
build_search_index = true
|
||||||
|
|
||||||
|
[markdown]
|
||||||
|
# Whether to do syntax highlighting
|
||||||
|
# Theme can be customised by setting the `highlight_theme` variable to a theme supported by Zola
|
||||||
|
highlight_code = true
|
||||||
|
|
||||||
|
[extra]
|
||||||
|
# Put all your custom variables here
|
BIN
public/404.gif
Before Width: | Height: | Size: 4 KiB |
|
@ -1,2 +0,0 @@
|
||||||
<!doctype html><html data-theme=dark lang=en xmlns=http://www.w3.org/1999/xhtml><head><meta charset=UTF-8><meta name=description><meta content="width=device-width,initial-scale=1" name=viewport><meta content=#b12633 name=theme-color><meta content=#c54854 media=(prefers-color-scheme:dark) name=theme-color><title>404 - Studio UMZU</title><link href=/ rel=canonical><link href=https://mastodon.online/@reprintedAron rel=me><meta content=@reprintedAron@mastodon.online name=fediverse:creator><link href=https://studio-umzu.de/favicon.png rel=icon type=image/png><link href=https://studio-umzu.de/apple-touch-icon.png rel=apple-touch-icon sizes=180x180 type=image/png><link crossorigin href=https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.7.2/css/all.min.css integrity=sha512-... referrerpolicy=no-referrer rel=stylesheet><link title="Studio UMZU - RSS Feed" href=https://studio-umzu.de/rss.xml rel=alternate type=application/rss+xml><link title="Studio UMZU - Atom Feed" href=https://studio-umzu.de/atom.xml rel=alternate type=application/atom+xml><style>:root{--accent-color:#b12633}[data-theme=dark]{--accent-color:#c54854}@media (prefers-color-scheme:dark){:root:not([data-theme=light]){--accent-color:#c54854}}</style><link href=https://studio-umzu.de/style.css rel=stylesheet><link href=https://studio-umzu.de/css/timeline.css rel=stylesheet><link href=https://studio-umzu.de/css/mermaid.css rel=stylesheet><link href=https://studio-umzu.de/css/skills.css rel=stylesheet><link href=https://studio-umzu.de/css/gallery.css rel=stylesheet><script defer src=https://studio-umzu.de/closable.js></script><script defer src=https://studio-umzu.de/copy-button.js></script><script data-goatcounter=https://awebsite.goatcounter.com/count defer src=https://studio-umzu.de/count.js></script><script defer src=https://studio-umzu.de/fuse.js></script><script defer src=https://studio-umzu.de/search-fuse.js></script><script defer src=https://studio-umzu.de/theme-switcher.js></script><script type=module>import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.esm.min.mjs';
|
|
||||||
mermaid.initialize({ startOnLoad: true });</script><meta content="Studio UMZU" property=og:site_name><meta content="404 - Studio UMZU" property=og:title><meta content=/ property=og:url><meta property=og:description><meta content=https://studio-umzu.de/card.png property=og:image><meta content=en_US property=og:locale><body><header id=site-nav><nav><a href=#main-content tabindex=0> Skip to Main Content </a><ul><li id=home><a href=https://studio-umzu.de> <i class=icon></i>Studio UMZU</a><li class=divider><li><a class=external href=https://friedrichwebergoizel.com>About Friedrich</a><li><a class=external href=https://aron.petau.net>About Aron</a><li id=search><button class=circle id=search-toggle title=Search><i class=icon></i></button><li id=language-switcher><details class=closable><summary class=circle title=Language><i class=icon></i></summary> <ul><li><a href=https://studio-umzu.de//de/ lang=de>Deutsch</a></ul></details><li id=theme-switcher><details class=closable><summary class=circle title=Theme><i class=icon></i></summary> <ul><li><button title="Switch to Light Theme" class=circle id=theme-light><i class=icon></i></button><li><button title="Switch to Dark Theme" class=circle id=theme-dark><i class=icon></i></button><li><button title="Use System Theme" class=circle id=theme-system><i class=icon></i></button></ul></details><li id=feed><details class=closable><summary class=circle title=Feed><i class=icon></i></summary> <ul><li><a href=https://studio-umzu.de/rss.xml>RSS</a><li><a href=https://studio-umzu.de/atom.xml>Atom</a></ul></details><li id=repo><a class=circle href=https://forgejo.petau.net/aron/studio-umzu title=Repository> <i class=icon></i> </a></ul></nav><div id=search-container><label class=visually-hidden for=search-bar>Search</label><input placeholder="Search for…" autocomplete=off disabled id=search-bar type=search><div id=search-results-container><div id=search-results></div></div></div></header><main id=main-content><picture><source media="(prefers-reduced-motion: reduce)" srcset=https://studio-umzu.de/404.png><img class="pixels transparent no-hover" alt=404 id=not-found src=https://studio-umzu.de/404.gif></picture><h1>Page Not Found</h1><p>The requested page could not be found. If you feel this is not normal, then you can create an issue on the issue tracker.<div class=buttons><a href=https://studio-umzu.de>Go Home</a><a class="colored external" href=https://forgejo.petau.net/aron/studio-umzu/issues>File an Issue</a></div><span class=hidden id=copy-code-text>Copy Code</span><span class=hidden id=search-index>https://studio-umzu.de/search_index.en.json</span><span class=hidden id=more-matches-text>$MATCHES more matches</span></main><footer id=site-footer><div class=carbonbadge id=wcb></div><script defer src=https://unpkg.com/website-carbon-badges@1.1.3/b.min.js></script><p><nav><ul><li><a class=external href=https://friedrichwebergoizel.com>About Friedrich</a><li><a class=external href=https://aron.petau.net>About Aron</a></ul></nav><p>© Studio UMZU, 2025<p><a class=external href=https://forgejo.petau.net/aron/studio-umzu>Website source</a><ul id=socials><li><a rel=" me" href=https://github.com/arontaupe title=GitHub> <i style="--icon:url("data:image/svg+xml,%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")" class=icon></i> <span>GitHub</span> </a><li><a href="mailto:aron@petau.net,f.goizel@yahoo.com?subject=[Workshop]" rel=" me" title=Mail> <i style="--icon:url("data:image/svg+xml,%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.5zm0 1.5v.243l10.5 7.006 10.5-7.006V6zm21 12V8.132l-10.038 6.697a.75.75 0 0 1-.924 0L1.5 8.132V18z'/%3E%3C/svg%3E")" class=icon></i> <span>Mail</span> </a></ul></footer>
|
|
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)}
|
|
Before Width: | Height: | Size: 183 KiB |
Before Width: | Height: | Size: 69 KiB |
|
@ -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;
|
|