Compare commits

..

28 Commits

Author SHA1 Message Date
b7017d4d3f implement small-headlines class especially for long legal texts 2023-08-06 19:40:32 +00:00
d5b64fc407 implement multi-col layout especially for long legal texts 2023-08-06 19:27:56 +00:00
b8e947fea4 only rewrite routes if LOCALHOST env variable is unset 2023-08-06 18:59:06 +00:00
6bb3dbaef7 display footer at page bottom 2023-08-06 18:18:56 +00:00
ce95e84992 restyle footer 2023-08-06 18:10:00 +00:00
4344b59cf9 imprint: fix markdown 2023-08-06 17:37:04 +00:00
1364b769de data-protection: fix markdown 2023-08-06 17:35:02 +00:00
4d3af43f1a data-protection: change order 2023-08-03 18:18:11 +00:00
df81b76531 change site theme 2023-08-03 18:14:02 +00:00
0ed0bb92c2 add imprint and data-protection footer 2023-08-03 18:13:24 +00:00
ea6ed885bf Merge branch 'css' into 'restructure'
Work on CSS

See merge request uniworx/uniworx.de!3
2023-07-26 11:56:14 +00:00
eb5e71d90a relative urls in webpack emitted bundles 2023-07-26 12:35:59 +02:00
0ad0613fa6 customize font 2023-07-26 12:16:04 +02:00
041e83c6f2 bootstrap based navigation 2023-07-26 11:35:59 +02:00
07db713b89 add fontawesome, implement basic mobile menu 2023-05-20 01:35:03 +00:00
60c96ec1ef header nav: fix submenu positioning 2023-05-19 20:43:21 +00:00
7a5bb77545 header nav: switch to dropdown menus 2023-05-19 20:31:16 +00:00
996a0760b6 header: tweak sizing 2023-05-19 20:16:05 +00:00
e1052c811a tweak submenu width for better ux 2023-05-19 19:34:40 +00:00
f5955cf405 add basic header css 2023-05-19 19:25:02 +00:00
59a6a0b55e switch to sass 2023-05-15 22:58:23 +00:00
21e0e9d883 add main.css 2023-05-15 22:52:08 +00:00
2e05a304b1 support special pages that are not concatenations of posts
Fixes #4
2023-05-15 15:48:05 +02:00
c91de20ef1 normalize links automagically by parsing _redirects
Fixes #2
2023-05-15 15:36:17 +02:00
014952290e add missing build tools to devShell 2023-05-15 12:08:10 +02:00
e2f8cf866d support for tag metadata (title/sorting)
Fixes #3
2023-05-15 12:03:43 +02:00
86800a404e Merge branch 'main' into 'restructure'
# Conflicts:
#   frontend/node_modules.gup
2023-05-13 19:24:03 +00:00
9fbd4ac9eb more dynamic structure 2023-05-13 21:22:11 +02:00
23 changed files with 1338 additions and 227 deletions

View File

@ -1,6 +1,4 @@
default:
image:
name: registry.uniworx.de/uniworx/containers/nix-attic:latest
image: nixpkgs/nix-flakes
workflow:
rules:
@ -22,7 +20,7 @@ stages:
pages:
stage: deploy
script: &build-script
script:
- nix develop -c gup public
artifacts:
paths:
@ -32,7 +30,9 @@ pages:
review:start:
stage: review
script: *build-script
script:
- rm -fv static/_redirects
- nix develop -c gup public
artifacts:
paths:
- public

2
Gupfile Normal file
View File

@ -0,0 +1,2 @@
checksum.gup:
**/.*.chksum

14
checksum.gup Normal file
View File

@ -0,0 +1,14 @@
#!/usr/bin/env zsh
gup --always
base=${2:t}
base=${base#"."}
base=${base%".chksum"}
base=${2:h}/${base}
while IFS= read -d $'\0' file; do
if [[ -f "${file}" ]]; then
b2sum "${file}"
else
echo "${file}"
fi
done > >(gup --contents) < <(find "${base}" -print0)

7
content/markdown.md Normal file
View File

@ -0,0 +1,7 @@
---
title: Seite unterstützt Markdown
tags: meta
sort: 0
---
Text kann auch in allen Pandoc-unterstützten Formaten angegeben werden, statt nur in HTML.
Hier: Markdown

8
content/tags.md Normal file
View File

@ -0,0 +1,8 @@
---
title: Tags sind echte Tags
tags:
- meta
- example
sort: 100
---
Beliebig viele Tags pro Item.

View File

@ -1,3 +1,11 @@
---
title: Seite befindet sich im Aufbau
tags:
- index
- meta
sort: -9001
---
```{=html}
<div class="px-4 py-5 my-5 text-center">
<h1 class="display-5 fw-bold text-body-emphasis">UniWorX Systems</h1>
<div class="col-lg-6 mx-auto">
@ -7,3 +15,4 @@
</p>
</div>
</div>
```

View File

@ -71,6 +71,8 @@
})
yarn
gup
zsh
coreutils
];
shellHook = ''
${config.pre-commit.installationScript}

View File

@ -1,6 +1,6 @@
#!/usr/bin/env sh
gup --always
gup -u node_modules
gup -u node_modules webpack.config.js postcss.config.js
gup -u .src.chksum
rm -rf dist
yarn run build

View File

@ -1,5 +1,5 @@
#!/usr/bin/env sh
gup --always
gup -u package.json yarn.lock
yarn install --frozen-lockfile --check-files --non-interactive
touch node_modules

View File

@ -1,11 +1,13 @@
{
"name": "my-webpack-project",
"name": "uniworx.de",
"version": "1.0.0",
"main": "index.js",
"private": true,
"dependencies": {
"@fortawesome/fontawesome-free": "^6.4.0",
"@popperjs/core": "^2.11.7",
"bootstrap": "^5.2.3"
"bootstrap": "^5.2.3",
"typeface-source-sans-pro": "^1.1.13"
},
"scripts": {
"build": "webpack"

View File

@ -1,3 +1,3 @@
import 'bootstrap/scss/bootstrap.scss'
import * as bootstrap from 'bootstrap'
import {} from 'bootstrap'
import {} from './main.sass'

64
frontend/src/main.sass Normal file
View File

@ -0,0 +1,64 @@
@use "sass:string"
@use "~@fortawesome/fontawesome-free/scss/fontawesome" as * with ( $fa-font-path: "~@fortawesome/fontawesome-pro/webfonts" )
@forward "~@fortawesome/fontawesome-free/scss/fontawesome"
@use "~@fortawesome/fontawesome-free/scss/solid"
@use "~typeface-source-sans-pro" as source-sans-pro
@use "~bootstrap/scss/bootstrap" with ( $primary: hsl(268, 20%, 34%), $navbar-toggler-padding-y: 0.5rem, $navbar-padding-x: 1rem, $font-family-sans-serif: string.unquote("\"Source Sans Pro\", system-ui, sans-serif") )
.custom-navbar-toggler-icon
@include fa-icon-solid($fa-var-times)
.collapsed &
@include fa-icon-solid($fa-var-bars)
body
display: flex
flex-direction: column
min-height: 100vh
main
flex: 1
margin: 1rem
.multi-col
columns: 3 500px
column-gap: 3em
column-rule: 1px solid #ddd
.small-headlines
h1
font-size: 2rem
h2
font-size: 1.5rem
h3
font-size: 1.25rem
font-weight: 500
h4,h5,h6
font-size: 1.0rem
font-weight: 600
footer > nav > ul
width: 100%
background-color: hsl(268, 20%, 34%)
margin: 1rem 0 0 0
padding: 1rem 0
display: flex
justify-content: center
gap: 1rem
a,a:visited,a:hover,a:active
text-decoration: none
color: white
opacity: 0.55
transition: 0.15s
&:hover,:active
opacity: 0.75
& > li
display: block

View File

@ -24,7 +24,8 @@ const config = {
chunkFilename: '[chunkhash].js',
filename: '[chunkhash].js',
path: path.resolve(__dirname, 'dist', `wp-${webpackVersion}`),
publicPath: `/wp-${webpackVersion}/`,
// publicPath: `/wp-${webpackVersion}/`,
publicPath: `./`,
hashFunction: 'shake256',
hashDigestLength: 36
},

File diff suppressed because it is too large Load Diff

View File

@ -6,9 +6,8 @@ default-extensions:
- NoImplicitPrelude
- ViewPatterns
- DerivingStrategies
- DeriveGeneric
- GeneralizedNewtypeDeriving
- TypeApplications
- MultiWayIf
language: GHC2021
executables:
site:
@ -33,3 +32,8 @@ executables:
- yaml
- containers
- Glob
- transformers
- mtl
- megaparsec
- text
- network-uri

237
special/data-protection.md Normal file
View File

@ -0,0 +1,237 @@
---
title: Datenschutzerklärung
---
<div markdown="1" class="multi-col small-headlines">
# Datenschutzerklärung
*Stand: 06.08.2023*
Wir informieren Sie nachfolgend gemäß den gesetzlichen Vorgaben des Datenschutzrechts (insb. gemäß BDSG n.F. und der europäischen Datenschutz-Grundverordnung „DSGVO“) über die Art, den Umfang und Zweck der Verarbeitung personenbezogener Daten durch unser Unternehmen. Diese Datenschutzerklärung gilt auch für unsere Webseiten und Social-Media-Profile. Bezüglich der Definition von Begriffen wie etwa „personenbezogene Daten“ oder „Verarbeitung“ verweisen wir auf Art. 4 DSGVO.
## Verantwortliche Personen
### Verantwortliche Person für den Inhalt
Unsere verantwortliche Person (nachfolgend „Verantwortlicher“) i.S.d. Art. 4 Zif. 7 DSGVO ist:
> UniWorX Systems
> Savitsstraße 43
> D-81929 München
> Bavaria, Germany
>
> Geschäftsführerin: Sarah Vaupel
> E-Mail-Adresse: sarah.vaupel@uniworx.de
### Datenschutzbeauftragte Person
> Sarah Vaupel
> Savitsstraße 43
> D-81929 München
> Bavaria, Germany
>
> E-Mail-Adresse: sarah.vaupel@uniworx.de
## Datenarten, Zwecke der Verarbeitung und Kategorien betroffener Personen
Nachfolgend informieren wir Sie über Art, Umfang und Zweck der Erhebung, Verarbeitung und Nutzung personenbezogener Daten.
1. **Arten der Daten, die wir verarbeiten**
Kommunikationsdaten (IP-Adresse etc.),
2. **Zwecke der Verarbeitung nach Art. 13 Abs. 1 c) DSGVO**
- Erfüllung gesetzlicher Aufbewahrungspflichten,
- Vermeidung von SPAM und Missbrauch,
- Maßnahmen der Sicherheit,
- Unterbrechungsfreier, sicherer Betrieb unserer Webseite,
3. **Kategorien der betroffenen Personen nach Art. 13 Abs. 1 e) DSGVO**
Besucher/Nutzer der Webseite.
Die betroffenen Personen werden zusammenfassend als „Nutzer“ bezeichnet.
## Rechtsgrundlagen der Verarbeitung personenbezogener Daten
Nachfolgend Informieren wir Sie über die Rechtsgrundlagen der Verarbeitung personenbezogener Daten.
1. Wenn wir Ihre Einwilligung für die Verarbeitung personenbezogenen Daten eingeholt haben, ist Art. 6 Abs. 1 S. 1 lit. a) DSGVO Rechtsgrundlage.
2. Ist die Verarbeitung zur Erfüllung eines Vertrags oder zur Durchführung vorvertraglicher Maßnahmen erforderlich, die auf Ihre Anfrage hin erfolgen, so ist Art. 6 Abs. 1 S. 1 lit. b) DSGVO Rechtsgrundlage.
3. Ist die Verarbeitung zur Erfüllung einer rechtlichen Verpflichtung erforderlich, der wir unterliegen (z.B. gesetzliche Aufbewahrungspflichten), so ist Art. 6 Abs. 1 S. 1 lit. c) DSGVO Rechtsgrundlage.
4. Ist die Verarbeitung erforderlich, um lebenswichtige Interessen der betroffenen Person oder einer anderen natürlichen Person zu schützen, so ist Art. 6 Abs. 1 S. 1 lit. d) DSGVO Rechtsgrundlage.
5. Ist die Verarbeitung zur Wahrung unserer oder der berechtigten Interessen eines Dritten erforderlich und überwiegen diesbezüglich Ihre Interessen oder Grundrechte und Grundfreiheiten nicht, so ist Art. 6 Abs. 1 S. 1 lit. f) DSGVO Rechtsgrundlage.
## Weitergabe personenbezogener Daten an Dritte und Auftragsverarbeiter
Ohne Ihre Einwilligung geben wir grundsätzlich keine Daten an Dritte weiter. Sollte dies doch der Fall sein, dann erfolgt die Weitergabe auf der Grundlage der zuvor genannten Rechtsgrundlagen z.B. bei der Weitergabe von Daten an Online-Paymentanbieter zur Vertragserfüllung oder aufgrund gerichtlicher Anordnung oder wegen einer gesetzlichen Verpflichtung zur Herausgabe der Daten zum Zwecke der Strafverfolgung, zur Gefahrenabwehr oder zur Durchsetzung der Rechte am geistigen Eigentum.
Wir setzen zudem Auftragsverarbeiter (externe Dienstleister z.B. zum Webhosting unserer Webseiten und Datenbanken) zur Verarbeitung Ihrer Daten ein. Wenn im Rahmen einer Vereinbarung zur Auftragsverarbeitung an die Auftragsverarbeiter Daten weitergegeben werden, erfolgt dies immer nach Art. 28 DSGVO. Wir wählen dabei unsere Auftragsverarbeiter sorgfältig aus, kontrollieren diese regelmäßig und haben uns ein Weisungsrecht hinsichtlich der Daten einräumen lassen. Zudem müssen die Auftragsverarbeiter geeignete technische und organisatorische Maßnahmen getroffen haben und die Datenschutzvorschriften gem. BDSG n.F. und DSGVO einhalten.
## Datenübermittlung in Drittstaaten
Durch die Verabschiedung der europäischen Datenschutz-Grundverordnung (DSGVO) wurde eine einheitliche Grundlage für den Datenschutz in Europa geschaffen. Ihre Daten werden daher vorwiegend durch Unternehmen verarbeitet, für die die DSGVO Anwendung findet. Sollte doch die Verarbeitung durch Dienste Dritter außerhalb der Europäischen Union oder des Europäischen Wirtschaftsraums stattfinden, so müssen diese die besonderen Voraussetzungen der Art. 44 ff. DSGVO erfüllen. Das bedeutet, die Verarbeitung erfolgt aufgrund besonderer Garantien, wie etwa die von der EU-Kommission offiziell anerkannte Feststellung eines der EU entsprechenden Datenschutzniveaus oder der Beachtung offiziell anerkannter spezieller vertraglicher Verpflichtungen, der so genannten „Standardvertragsklauseln“.
Soweit wir aufgrund der Unwirksamkeit des sog. „Privacy Shields“, nach Art. 49 Abs. 1 S. 1 lit. a) DSGVO die ausdrückliche Einwilligung in die Datenübermittlung in die USA von Ihnen einholen, weisen wir diesbezüglich auf das Risiko eines geheimen Zugriffs durch US-Behörden und die Nutzung der Daten zu Überwachungszwecken, ggf. ohne Rechtsbehelfsmöglichkeiten für EU-Bürger, hin.
## Löschung von Daten und Speicherdauer
Sofern nicht in dieser Datenschutzerklärung ausdrücklich angegeben, werden Ihre personenbezogen Daten gelöscht oder gesperrt, sobald die zur Verarbeitung erteilte Einwilligung von Ihnen widerrufen wird oder der Zweck für die Speicherung entfällt bzw. die Daten für den Zweck nicht mehr erforderlich sind, es sei denn deren weitere Aufbewahrung ist zu Beweiszwecken erforderlich oder dem stehen gesetzliche Aufbewahrungspflichten entgegenstehen. Darunter fallen etwa handelsrechtliche Aufbewahrungspflichten von Geschäftsbriefen nach § 257 Abs. 1 HGB (6 Jahre) sowie steuerrechtliche Aufbewahrungspflichten nach § 147 Abs. 1 AO von Belegen (10 Jahre). Wenn die vorgeschriebene Aufbewahrungsfrist abläuft, erfolgt eine Sperrung oder Löschung Ihrer Daten, es sei denn die Speicherung ist weiterhin für einen Vertragsabschluss oder zur Vertragserfüllung erforderlich.
## Bestehen einer automatisierten Entscheidungsfindung
Wir setzen keine automatische Entscheidungsfindung und kein Profiling ein.
## Bereitstellung unserer Webseite und Erstellung von Logfiles
1. Wenn Sie unsere Webseite lediglich informatorisch nutzen (also keine Registrierung und auch keine anderweitige Übermittlung von Informationen), erheben wir nur die personenbezogenen Daten, die Ihr Browser an unseren Server übermittelt. Wenn Sie unsere Webseite betrachten möchten, erheben wir die folgenden Daten:
- IP-Adresse;
- Internet-Service-Provider des Nutzers;
- Datum und Uhrzeit des Abrufs;
- Browsertyp;
- Sprache und Browser-Version;
- Inhalt des Abrufs;
- Zeitzone;
- Zugriffsstatus/HTTP-Statuscode;
- Datenmenge;
- Webseiten, von denen die Anforderung kommt;
- Betriebssystem.
Eine Speicherung dieser Daten zusammen mit anderen personenbezogenen Daten von Ihnen findet nicht statt.
2. Diese Daten dienen dem Zweck der nutzerfreundlichen, funktionsfähigen und sicheren Auslieferung unserer Webseite an Sie mit Funktionen und Inhalten sowie deren Optimierung und statistischen Auswertung.
3. Rechtsgrundlage hierfür ist unser in den obigen Zwecken auch liegendes berechtigtes Interesse an der Datenverarbeitung nach Art. 6 Abs. 1 S.1 lit. f) DSGVO.
4. Wir speichern aus Sicherheitsgründen diese Daten in Server-Logfiles für die Speicherdauer von 30 Tagen. Nach Ablauf dieser Frist werden diese automatisch gelöscht, es sei denn wir benötigen deren Aufbewahrung zu Beweiszwecken bei Angriffen auf die Serverinfrastruktur oder anderen Rechtsverletzungen.
## Präsenz in sozialen Medien
1. Wir unterhalten in sozialen Medien Profile bzw. Fanpages. Bei der Nutzung und dem Aufruf unseres Profils im jeweiligen Netzwerk durch Sie gelten die jeweiligen Datenschutzhinweise und Nutzungsbedingungen des jeweiligen Netzwerks.
2. **Datenkategorien und Beschreibung der Datenverarbeitung:**
- Nutzungsdaten,
- Kontaktdaten,
- Inhaltsdaten,
- Bestandsdaten.
Ferner werden die Daten der Nutzer innerhalb sozialer Netzwerke im Regelfall für Marktforschungs- und Werbezwecke verarbeitet. So können z.B. anhand des Nutzungsverhaltens und sich daraus ergebender Interessen der Nutzer Nutzungsprofile erstellt werden. Die Nutzungsprofile können wiederum verwendet werden, um z.B. Werbeanzeigen innerhalb und außerhalb der Netzwerke zu schalten, die mutmaßlich den Interessen der Nutzer entsprechen. Zu diesen Zwecken werden im Regelfall Cookies auf den Rechnern der Nutzer gespeichert, in denen das Nutzungsverhalten und die Interessen der Nutzer gespeichert werden. Ferner können in den Nutzungsprofilen auch Daten unabhängig der von den Nutzern verwendeten Geräte gespeichert werden (insbesondere, wenn die Nutzer Mitglieder der jeweiligen Plattformen sind und bei diesen eingeloggt sind). Für eine detaillierte Darstellung der jeweiligen Verarbeitungsformen und der Widerspruchsmöglichkeiten (Opt-Out) verweisen wir auf die Datenschutzerklärungen und Angaben der Betreiber der jeweiligen Netzwerke. Auch im Fall von Auskunftsanfragen und der Geltendmachung von Betroffenenrechten weisen wir darauf hin, dass diese am effektivsten bei den Anbietern geltend gemacht werden können. Nur die Anbieter haben jeweils Zugriff auf die Daten der Nutzer und können direkt entsprechende Maßnahmen ergreifen und Auskünfte geben. Sollten Sie dennoch Hilfe benötigen, dann können Sie sich an uns wenden.
3. **Zweck der Verarbeitung:**
- Kommunikation mit den auf den sozialen Netzwerken angeschlossenen und registrierten Nutzern;
- Information und Werbung für unsere Produkte, Angebote und Dienstleistungen;
- Außerdarstellung und Imagepflege;
- Auswertung und Analyse der Nutzer und Inhalte unserer Präsenzen in den sozialen Medien.
4. **Rechtsgrundlagen:**
Die Rechtsgrundlage für die Verarbeitung der personenbezogenen Daten ist unser in den obigen Zwecken liegendes berechtigtes Interesse gemäß Art. 6 Abs. 1 S. 1 lit. f) DSGVO. Soweit Sie uns bzw. dem Verantwortlichen des sozialen Netzwerks eine Einwilligung in die Verarbeitung Ihrer personenbezogenen Daten erteilt haben, ist Rechtsgrundlage Art. 6 Abs. 1 S. 1 lit. a) i.V.m. Art. 7 DSGVO.
5. **Datenübermittlung/Empfängerkategorie:**
Soziales Netzwerk.
6. Die Datenschutzhinweise, Auskunftsmöglichkeiten und Widerspruchmöglichkeiten (Opt-Out) der jeweiligen Netzwerke / Diensteanbieter finden Sie hier:
- **XING** Diensteanbieter: XING AG, Dammtorstra&szlig;e 29-32, 20354 Hamburg, Deutschland) - Datenschutzerkl&auml;rung/ Opt-Out:&nbsp;<a href="https://privacy.xing.com/de/datenschutzerklaerung" target="_blank" rel="nofollow">https://privacy.xing.com/de/datenschutzerklaerung</a>
- **LinkedIn** Diensteanbieter: LinkedIn Ireland Unlimited Company, Wilton Place, Dublin 2, Irland) &ndash; Datenschutzerkl&auml;rung:&nbsp;<a href="https://www.linkedin.com/legal/privacy-policy" target="_blank" rel="nofollow">https://www.linkedin.com/legal/privacy-policy</a>, Cookie-Richtlinie und Opt-Out:&nbsp;<a href="https://www.linkedin.com/legal/cookie-policy" target="_blank" rel="nofollow">https://www.linkedin.com/legal/cookie-policy</a>
## Social-Media-Plug-ins
1. Wir setzen auf unserer Webseite Social-Media-Plug-ins von sozialen Netzwerken ein. Dabei nutzen wir die sog.&nbsp;&bdquo;Zwei-Klick-L&ouml;sung&ldquo;-Shariff&nbsp;von c&rsquo;t bzw. heise.de: <a href="https://www.heise.de/ct/artikel/Shariff-Social-Media-Buttons-mit-Datenschutz-2467514.html" rel="nofollow" target="_blank">https://www.heise.de/ct/artikel/Shariff-Social-Media-Buttons-mit-Datenschutz-2467514.html</a>; Dienstanbieter: Heise Medien GmbH &amp; Co. KG, Karl-Wiechert-Allee 10, 30625 Hannover, Deutschland; Datenschutzerkl&auml;rung: <a href="https://www.heise.de/Datenschutzerklaerung-der-Heise-Medien-GmbH-Co-KG-4860.html" rel="nofollow" target="_blank">https://www.heise.de/Datenschutzerklaerung-der-Heise-Medien-GmbH-Co-KG-4860.html</a>.
2. **Datenkategorie und Beschreibung der Datenverarbeitung:**
- Nutzungsdaten,
- Inhaltsdaten,
- Bestandsdaten.
Beim Abruf unserer Webseite werden durch &bdquo;Shariff&ldquo;&nbsp;<strong>keine personenbezogenen</strong> Daten&nbsp;an die Drittanbieter der Social-Plug-ins &uuml;bermittelt. Neben dem Logo bzw. der Marke des sozialen Netzwerks finden Sie einen Regler, mit dem Sie das Plug-in per Klick aktivieren k&ouml;nnen. Diese Aktivierung stellt Ihre <strong>Einwilligung</strong> in der Form dar, dass der jeweilige Anbieter des sozialen Netzwerks die Information erh&auml;lt, dass Sie unsere Webseite aufgerufen haben und Ihre personenbezogenen Daten an den Anbieter des Plug-ins &uuml;bermittelt und dort gespeichert werden. Hierbei handelt es sich um sog. Thirdparty Cookies. Bei einigen Anbietern wie Facebook und XING wird nach deren Angaben Ihre IP nach der Erhebung sofort anonymisiert. Die &uuml;ber den Nutzer erhobenen Daten speichert der Plug-in-Anbieter als Nutzungsprofile.
*Sie können Ihre Einwilligung jederzeit durch die Deaktivierung des Reglers widerrufen.*
3. **Zweck der Datenverarbeitung:**
- Verbesserung und Optimierung unserer Webseite;
- Steigerung unserer Bekanntheit mittels sozialer Netzwerke;
- Möglichkeit der Interaktion mit Ihnen und der Nutzer untereinander über soziale Netzwerke;
- Werbung, Analyse und/oder bedarfsgerechten Gestaltung der Webseite.
4. **Rechtsgrundlagen:**
Die Rechtsgrundlage für die Verarbeitung der personenbezogenen Daten ist unser in den obigen Zwecken liegendes berechtigtes Interesse gemäß Art. 6 Abs. 1 S. 1 lit. f) DSGVO. Soweit Sie uns bzw. dem Verantwortlichen des sozialen Netzwerks eine Einwilligung in die Verarbeitung Ihrer personenbezogenen Daten erteilt haben, ist Rechtsgrundlage Art. 6 Abs. 1 S. 1 lit. a) i.V.m. Art. 7 DSGVO. Bei vorvertraglichen Anfragen oder bei der Nutzung Ihrer personenbezogenen Daten zur Vertragserfüllung, ist Art. 6 Abs. 1 S. 1 lit. b) DSGVO Rechtsgrundlage.
5. **Datenübermittlung/Empfängerkategorie:**
Soziales Netzwerk.
6. **Genutzte soziale Netzwerke und Widerspruch:**
Wir verweisen hinsichtlich des Zwecks und Umfangs der Datenerhebung und Verarbeitung auf die jeweiligen Datenschutzerklärungen der sozialen Netzwerke. Zudem finden Sie dort auch Hinweise zu Ihren Rechten und Einstellungsmöglichkeiten zum Schutz Ihrer personenbezogenen Daten. Ihnen steht ein Widerspruchsrecht gegen die Bildung dieser Nutzerprofile zu, wobei Sie sich zur Ausübung dieser Rechte direkt an den jeweiligen Plug-in-Anbieter wenden können.
## XING
1. Wir haben auf unserer Webseite Plug-ins vom sozialen Netzwerk XING (XING AG, Dammtorstraße 29-32, 20354 Hamburg, Deutschland) im Rahmen der sog. „Zwei-Klick-Lösung“ von Shariff integriert. Diese erkennen Sie am Share-Button mit weißem Logo von XING und dem „X“ Symbol auf grünem Hintergrund.
2. Wenn Sie auf unserer Webseite den Share-Button von XING willentlich aktivieren, führt dies beim Aufruf der jeweiligen Internetseite dazu, dass Ihr Browser eine Verbindung mit dem Server von XING aufbaut. Dabei werden laut XING keine Daten über den Aufruf gespeichert, aus denen XING einen unmittelbaren Personenbezug herleiten könnte. XING speichert insbesondere keine IP-Adressen von Ihnen und verwendet auch keine Cookies. Beim Klick auf den Share-Button werden Sie zur Startseite von XING umgeleitet, auf der Sie dann - falls Sie eingeloggt sind unsere Seite empfehlen können, was dem Zweck der Steigerung unserer Bekanntheit und Reichweite dient. Hinsichtlich dieser Aktivitäten auf der XING Plattform gilt die unten genannte Datenschutzerklärung von XING.
3. Wenn Sie sich bei XING vor dem Besuch unserer Webseite ausloggen und Ihre Cookies löschen, werden bei der Aktivierung des Plug-ins keine Daten über den Besuch unserer Webseite Ihrem Profil auf XING zugeordnet.
4. Zweck und Umfang der Datenerhebung sowie ihre weitere Verarbeitung und Nutzung der Daten durch XING sowie Ihre diesbez&uuml;glichen Rechte und Einstellungsm&ouml;glichkeiten zum Schutz Ihrer Privatsph&auml;re, k&ouml;nnen Sie den Datenschutzhinweisen von XING zum Share-Button entnehmen unter&nbsp;<a href="https://www.xing.com/app/share%3Fop%3Ddata_protection" target="_blank" rel="nofollow">https://www.xing.com/app/share%3Fop%3Ddata_protection</a>&nbsp;sowie der allgemeinen Datenschutzerkl&auml;rung von XING unter <a href="https://privacy.xing.com/de/datenschutzerklaerung" target="_blank" rel="nofollow">https://privacy.xing.com/de/datenschutzerklaerung</a>.<br /><br /></li>
## Rechte der betroffenen Person
1. **Widerspruch oder Widerruf gegen die Verarbeitung Ihrer Daten**
Soweit die Verarbeitung auf Ihrer Einwilligung gemäß Art. 6 Abs. 1 S. 1 lit. a), Art. 7 DSGVO beruht, haben Sie das Recht, die Einwilligung jederzeit zu widerrufen. Die Rechtmäßigkeit der aufgrund der Einwilligung bis zum Widerruf erfolgten Verarbeitung wird dadurch nicht berührt.
Soweit wir die Verarbeitung Ihrer personenbezogenen Daten auf die Interessenabwägung gemäß Art. 6 Abs. 1 S. 1 lit. f) DSGVO stützen, können Sie Widerspruch gegen die Verarbeitung einlegen. Dies ist der Fall, wenn die Verarbeitung insbesondere nicht zur Erfüllung eines Vertrags mit Ihnen erforderlich ist, was von uns jeweils bei der nachfolgenden Beschreibung der Funktionen dargestellt wird. Bei Ausübung eines solchen Widerspruchs bitten wir um Darlegung der Gründe, weshalb wir Ihre personenbezogenen Daten nicht wie von uns durchgeführt verarbeiten sollten. Im Falle Ihres begründeten Widerspruchs prüfen wir die Sachlage und werden entweder die Datenverarbeitung einstellen bzw. anpassen oder Ihnen unsere zwingenden schutzwürdigen Gründe aufzeigen, aufgrund derer wir die Verarbeitung fortführen.
Sie können der Verarbeitung Ihrer personenbezogenen Daten für Zwecke der Werbung und Datenanalyse jederzeit widersprechen. Das Widerspruchsrecht können Sie kostenfrei ausüben. Über Ihren Werbewiderspruch können Sie uns unter folgenden Kontaktdaten informieren:
> UniWorX Systems
> Savitsstraße 43
> D-81929 München
> Bavaria, Germany
>
> Geschäftsführerin: Sarah Vaupel
> E-Mail-Adresse: sarah.vaupel@uniworx.de
2. **Recht auf Auskunft**
Sie haben das Recht, von uns eine Bestätigung darüber zu verlangen, ob Sie betreffende personenbezogene Daten verarbeitet werden. Sofern dies der Fall ist, haben Sie ein Recht auf Auskunft über Ihre bei uns gespeicherten persönlichen Daten nach Art. 15 DSGVO. Dies beinhaltet insbesondere die Auskunft über die Verarbeitungszwecke, die Kategorie der personenbezogenen Daten, die Kategorien von Empfängern, gegenüber denen Ihre Daten offengelegt wurden oder werden, die geplante Speicherdauer, die Herkunft ihrer Daten, sofern diese nicht direkt bei Ihnen erhoben wurden.
3. **Recht auf Berichtigung**
Sie haben ein Recht auf Berichtigung unrichtiger oder auf Vervollständigung richtiger Daten nach Art. 16 DSGVO.
4. **Recht auf Löschung**
Sie haben ein Recht auf Löschung Ihrer bei uns gespeicherten Daten nach Art. 17 DSGVO, es sei denn gesetzliche oder vertraglichen Aufbewahrungsfristen oder andere gesetzliche Pflichten bzw. Rechte zur weiteren Speicherung stehen dieser entgegen.
5. **Recht auf Einschränkung**
Sie haben das Recht, eine Einschränkung bei der Verarbeitung Ihrer personenbezogenen Daten zu verlangen, wenn eine der Voraussetzungen in Art. 18 Abs. 1 lit. a) bis d) DSGVO erfüllt ist:
- Wenn Sie die Richtigkeit der Sie betreffenden personenbezogenen für eine Dauer bestreiten, die es dem Verantwortlichen ermöglicht, die Richtigkeit der personenbezogenen Daten zu überprüfen;
- die Verarbeitung unrechtmäßig ist und Sie die Löschung der personenbezogenen Daten ablehnen und stattdessen die Einschränkung der Nutzung der personenbezogenen Daten verlangen;
- der Verantwortliche die personenbezogenen Daten für die Zwecke der Verarbeitung nicht länger benötigt, Sie diese jedoch zur Geltendmachung, Ausübung oder Verteidigung von Rechtsansprüchen benötigen, oder
- wenn Sie Widerspruch gegen die Verarbeitung gemäß Art. 21 Abs. 1 DSGVO eingelegt haben und noch nicht feststeht, ob die berechtigten Gründe des Verantwortlichen gegenüber Ihren Gründen überwiegen.
6. **Recht auf Datenübertragbarkeit**
Sie haben ein Recht auf Datenübertragbarkeit nach Art. 20 DSGVO, was bedeutet, dass Sie die bei uns über Sie gespeicherten personenbezogenen Daten in einem strukturierten, gängigen und maschinenlesbaren Format erhalten können oder die Übermittlung an einen anderen Verantwortlichen verlangen können.
7. **Recht auf Beschwerde**
Sie haben ein Recht auf Beschwerde bei einer Aufsichtsbehörde. In der Regel können Sie sich hierfür an die Aufsichtsbehörde insbesondere in dem Mitgliedstaat ihres Aufenthaltsorts, ihres Arbeitsplatzes oder des Orts des mutmaßlichen Verstoßes wenden.
## Datensicherheit
Um alle personenbezogen Daten, die an uns übermittelt werden, zu schützen und um sicherzustellen, dass die Datenschutzvorschriften von uns, aber auch unseren externen Dienstleistern eingehalten werden, haben wir geeignete technische und organisatorische Sicherheitsmaßnahmen getroffen. Deshalb werden unter anderem alle Daten zwischen Ihrem Browser und unserem Server über eine sichere SSL-Verbindung verschlüsselt übertragen.
</div>

45
special/imprint.md Normal file
View File

@ -0,0 +1,45 @@
---
title: Impressum
---
<div markdown="1" class="multi-col small-headlines">
# Impressum
## Angaben gemäß § 5 TMG
> Sarah Vaupel
> UniWorX Systems
> Savitsstraße 43
> D-81929 München
> Bavaria, Germany
>
> Telefon: +49 179 4130707
> E-Mail: [sarah.vaupel@uniworx.de](mailto:sarah.vaupel@uniworx.de)
## Verantwortlich für den Inhalt gemäß § 55 Abs. 2 RStV
> Sarah Vaupel
> UniWorX Systems
> Savitsstraße 43
> D-81929 München
> Bavaria, Germany
## Disclaimer Rechtliche Hinweise
### § 1 Warnhinweis zu Inhalten
Die kostenlosen und frei zugänglichen Inhalte dieser Webseite wurden mit größtmöglicher Sorgfalt erstellt. Der Anbieter dieser Webseite übernimmt jedoch keine Gewähr für die Richtigkeit und Aktualität der bereitgestellten kostenlosen und frei zugänglichen journalistischen Ratgeber und Nachrichten. Namentlich gekennzeichnete Beiträge geben die Meinung des jeweiligen Autors und nicht immer die Meinung des Anbieters wieder. Allein durch den Aufruf der kostenlosen und frei zugänglichen Inhalte kommt keinerlei Vertragsverhältnis zwischen dem Nutzer und dem Anbieter zustande, insoweit fehlt es am Rechtsbindungswillen des Anbieters.
### § 2 Externe Links
Diese Website enthält Verknüpfungen zu Websites Dritter („externe Links“). Diese Webseiten unterliegen der Haftung der jeweiligen Betreiber. Der Anbieter hat bei der erstmaligen Verknüpfung der externen Links die fremden Inhalte daraufhin überprüft, ob etwaige Rechtsverstöße bestehen. Zu dem Zeitpunkt waren keine Rechtsverstöße ersichtlich. Der Anbieter hat keinerlei Einfluss auf die aktuelle und zukünftige Gestaltung und auf die Inhalte der verknüpften Seiten. Das Setzen von externen Links bedeutet nicht, dass sich der Anbieter die hinter dem Verweis oder Link liegenden Inhalte zu Eigen macht. Eine ständige Kontrolle der externen Links ist für den Anbieter ohne konkrete Hinweise auf Rechtsverstöße nicht zumutbar. Bei Kenntnis von Rechtsverstößen werden jedoch derartige externe Links unverzüglich gelöscht.
### § 3 Urheber- und Leistungsschutzrechte
Die auf dieser Website veröffentlichten Inhalte unterliegen dem deutschen Urheber- und Leistungsschutzrecht. Jede vom deutschen Urheber- und Leistungsschutzrecht nicht zugelassene Verwertung bedarf der vorherigen schriftlichen Zustimmung des Anbieters oder jeweiligen Rechteinhabers. Dies gilt insbesondere für Vervielfältigung, Bearbeitung, Übersetzung, Einspeicherung, Verarbeitung bzw. Wiedergabe von Inhalten in Datenbanken oder anderen elektronischen Medien und Systemen. Inhalte und Rechte Dritter sind dabei als solche gekennzeichnet. Die unerlaubte Vervielfältigung oder Weitergabe einzelner Inhalte oder kompletter Seiten ist nicht gestattet und strafbar. Lediglich die Herstellung von Kopien und Downloads für den persönlichen, privaten und nicht kommerziellen Gebrauch ist erlaubt.
Die Darstellung dieser Website in fremden Frames ist nur mit schriftlicher Erlaubnis zulässig.
### § 4 Besondere Nutzungsbedingungen
Soweit besondere Bedingungen für einzelne Nutzungen dieser Website von den oben genannten Paragraphen abweichen, wird an entsprechender Stelle ausdrücklich darauf hingewiesen. In diesem Falle gelten im jeweiligen Einzelfall die besonderen Nutzungsbedingungen.
</div>

View File

@ -4,17 +4,42 @@ import Prelude
import Hakyll
import qualified Data.List as List
import Data.Bool
import Data.List qualified as List
import Data.Maybe
import System.FilePath
import qualified System.FilePath.Glob as Glob
import qualified Data.Yaml as Yaml
import System.FilePath
import System.FilePath.Glob qualified as Glob
import Data.Yaml qualified as Yaml
import Data.Map (Map)
import qualified Data.Map as Map
import Data.Map qualified as Map
import Control.Monad
import Control.Monad.Reader.Class
import Control.Monad.Trans.Maybe
import Control.Monad.Trans.Reader (Reader, runReader)
import Control.Applicative
import Data.Text.Lazy qualified as Lazy (Text)
import Data.Text.Lazy.IO qualified as LT
import Text.Megaparsec (Parsec, ParsecT)
import Text.Megaparsec qualified as MP
import Text.Megaparsec.Char qualified as MP
import Data.Text (Text)
import Data.Text qualified as T
import Control.Exception
import System.IO.Error
import Data.Void
import Network.URI
import System.Environment (lookupEnv)
config :: Configuration
config =
@ -22,52 +47,204 @@ config =
{ destinationDirectory = "public"
}
stripPathPrefix :: FilePath -> Routes
routeAsFilePath :: (FilePath -> FilePath) -> Routes
routeAsFilePath f = customRoute $ f . toFilePath
stripPathPrefix :: FilePath -> (FilePath -> FilePath)
stripPathPrefix (splitDirectories -> prefix) =
customRoute $
joinPath . (\x -> fromMaybe x $ List.stripPrefix prefix x) . splitDirectories . toFilePath
joinPath . (\x -> fromMaybe x $ List.stripPrefix prefix x) . splitDirectories
handleIf :: Exception e => (e -> Bool) -> (e -> IO a) -> IO a -> IO a
handleIf predicate handler = handle $ \exc -> bool throwIO handler (predicate exc) exc
metadataSort :: [Item w] -> Compiler [Item w]
metadataSort = sortOnM $ \Item{itemIdentifier} -> maybe (0 :: Integer) read <$> getMetadataField itemIdentifier "sort"
where
sortOnM :: forall m a b. (Monad m, Ord b) => (a -> m b) -> [a] -> m [a]
sortOnM f = fmap (map snd . List.sortOn fst) . mapM (\x -> (,x) <$> f x)
unwrapped :: Snapshot
unwrapped = "unwrapped"
main :: IO ()
main = hakyllWith config $ do
frontendManifest <-
preprocess $
Yaml.decodeFileThrow @_ @(Map String [FilePath]) "frontend/dist/.manifest.yaml"
main =
lookupEnv "LOCALHOST" >>= \((Nothing /=) -> localhost) -> hakyllWith config $ do
frontendManifest <-
preprocess $
Yaml.decodeFileThrow @_ @(Map String [FilePath]) "frontend/dist/.manifest.yaml"
let
frontendContext = jsContext <> cssContext
where
cssContext = listField "css" innerContext genCSSItems
where
innerContext = urlField "url"
genCSSItems = genManifestItems $ Glob.compile "**/*.css"
jsContext = listField "js" innerContext genCSSItems
where
innerContext = urlField "url"
genCSSItems = genManifestItems $ Glob.compile "**/*.js"
match "content/index.html" $ do
route $ stripPathPrefix "content"
genManifestItems :: Glob.Pattern -> Compiler [Item CopyFile]
genManifestItems p = do
let entryPoint = "main"
resources = filter (Glob.match p) $ frontendManifest Map.! entryPoint
forM resources $ load . fromFilePath . ("frontend/dist" </>) . dropDrive
let context =
defaultContext
<> jsContext
<> cssContext
netlifyRedirects <-
if localhost
then return []
else
preprocess . handleIf isDoesNotExistError (const $ return []) $
let pNetlify :: ParsecT Void Lazy.Text m [(FilePath, FilePath)]
pNetlify = catMaybes <$> MP.sepBy (MP.space *> pLine <* MP.hspace) pEOL <* MP.eof
where
pEOL :: ParsecT Void Lazy.Text m ()
pEOL = void . MP.label "linebreak" $ MP.eol
pLine :: ParsecT Void Lazy.Text m (Maybe (FilePath, FilePath))
pLine = MP.label "line" $ (mempty <$ pComment) <|> pRedirect <|> pure Nothing
pComment :: ParsecT Void Lazy.Text m ()
pComment = void $ MP.char '#' *> MP.label "comment" (MP.manyTill MP.anySingle $ MP.lookAhead MP.eol)
pRedirect :: ParsecT Void Lazy.Text m (Maybe (FilePath, FilePath))
pRedirect = do
fromRoute <- MP.label "fromRoute" $ MP.manyTill MP.anySingle MP.separatorChar
MP.hspace
toRoute <- MP.label "toRoute" $ MP.manyTill MP.anySingle MP.separatorChar
MP.hspace
redirectMode <- MP.label "mode" $ asum [MP.string "200", MP.string "301", MP.string "302"]
return $
if
| redirectMode == "200" -> Just (fromRoute, toRoute)
| otherwise -> Nothing
in either throwIO return =<< MP.runParserT pNetlify "static/_redirects" =<< LT.readFile "static/_redirects"
let
renderRoute r
| fromRoute : _ <- mapMaybe (matchNetlifyRedirect r) netlifyRedirects =
fromRoute
| otherwise =
r
where
matchNetlifyRedirect :: FilePath -> (FilePath, FilePath) -> Maybe FilePath
matchNetlifyRedirect r' (fromRoute, toRoute) = do
tokens <- MP.parseMaybe pToSpec toRoute
Right subst <- return $ runReader (MP.runParserT (pRoute tokens <* MP.eof) "" r') Map.empty
return . T.unpack $ Map.foldrWithKey doSubst (T.pack fromRoute) subst
where
pToSpec :: Parsec Void FilePath [Either FilePath String]
pToSpec =
MP.some $
Left <$> MP.someTill (MP.anySingleBut ':') (MP.lookAhead $ MP.eof <|> void (MP.single ':'))
<|> Right <$> (MP.char ':' *> MP.some MP.letterChar)
pRoute :: [Either FilePath String] -> ParsecT Void FilePath (Reader (Map String String)) (Map String String)
pRoute [] = MP.eof *> ask
pRoute (t : ts) = case t of
Left str -> MP.string str *> pRoute ts
Right p -> do
pVal <- asks $ Map.lookup p
case pVal of
Nothing -> do
mLength <- length <$> MP.getInput
asum . flip map [0 .. mLength] $ \l -> MP.try $ do
val <- MP.takeP (Just $ ':' : p) l
newSubst <- asks $ Map.insert p val
newSubst <$ local (const newSubst) (pRoute ts)
Just pVal' -> MP.string pVal' *> ask
cssContext = listField "css" innerContext genCSSItems
where
innerContext = urlField "url"
genCSSItems = genManifestItems $ Glob.compile "**/*.css"
jsContext = listField "js" innerContext genCSSItems
where
innerContext = urlField "url"
genCSSItems = genManifestItems $ Glob.compile "**/*.js"
doSubst :: String -> String -> Text -> Text
doSubst k s = T.intercalate (T.pack s) . T.splitOn (T.pack $ ':' : k)
normalizeUrls :: Item String -> Compiler (Item String)
normalizeUrls item = do
itemRoute <- getRoute $ itemIdentifier item
let relativizeUrls' x = case itemRoute of
Just r
| "/" `List.isPrefixOf` x && not ("//" `List.isPrefixOf` x) ->
toSiteRoot r ++ x
_other -> x
overPath f str = case parseURIReference str of
Nothing -> f str
Just uri@URI{uriPath} -> uriToString id uri{uriPath = f uriPath} mempty
return $ withUrls (relativizeUrls' . overPath renderRoute) <$> item
genManifestItems :: Glob.Pattern -> Compiler [Item CopyFile]
genManifestItems p = do
let entryPoint = "main"
resources = filter (Glob.match p) $ frontendManifest Map.! entryPoint
forM resources $ load . fromFilePath . ("frontend/dist" </>) . dropDrive
tags <- buildTags "content/**" $ fromCapture "tags/*.html"
compile $ do
getResourceBody
>>= loadAndApplyTemplate "templates/site-layout.html" context
>>= relativizeUrls
let
applySiteLayout = loadAndApplyTemplate "templates/site-layout.html" . (<> ctx')
where
ctx' =
mconcat
[ listField "tags-nav" defaultContext (metadataSort <=< mapM (uncurry renderTagNav) $ tagsMap tags)
, listField "special-nav" defaultContext $ metadataSort =<< mapM (flip loadSnapshot unwrapped) =<< getMatches (fromGlob "special/**")
, frontendContext
, defaultContext
]
renderTagNav tag' ids = do
tagItems' <- getMatches . fromGlob $ toFilePath (tagsMakeId tags tag') -<.> "*"
let
tagItem' = return $ Item (fromMaybe (tagsMakeId tags tag') $ listToMaybe tagItems') (mempty :: String)
match "frontend/dist/wp-*/**" $ do
route $ stripPathPrefix "frontend/dist"
navRoute = "/" <> tag' <> ".html"
compile copyFileCompiler
tagNavCtx =
mconcat
[ constField "tag" tag'
, field "title" . const $
fmap (fromMaybe tag') . runMaybeT . asum $
map (\itemId -> MaybeT $ getMetadataField itemId "title") tagItems'
, constField "route" navRoute
, listField "posts" (constField "tag" tag' <> constField "route" navRoute <> postContext) (metadataSort =<< mapM load ids)
]
tagItem'
>>= loadAndApplyTemplate "templates/tag-nav.html" tagNavCtx
>>= normalizeUrls
postContext =
mconcat
[ field "identifier" (return . takeBaseName . toFilePath . itemIdentifier)
, defaultContext
]
specialContext = defaultContext
match "templates/*" $ compile templateBodyCompiler
match "content/**" $ do
compile $
pandocCompiler
>>= normalizeUrls
match "static/**" $ do
route $ stripPathPrefix "static"
compile copyFileCompiler
match "special/**" $ do
route . routeAsFilePath $ (-<.> "html") . stripPathPrefix "special"
compile $
pandocCompiler
>>= saveSnapshot unwrapped
>>= applySiteLayout specialContext
>>= normalizeUrls
forM_ (tagsMap tags) $ \(tag, fromList -> posts) ->
rulesExtraDependencies [tagsDependency tags] $ do
tagItems <- getMatches . fromGlob $ toFilePath (tagsMakeId tags tag) -<.> "*"
let tagItem = pandocCompiler <|> makeItem mempty
rule
| [] <- tagItems = create [tagsMakeId tags tag]
| otherwise = match (fromList tagItems)
rule $ do
route . routeAsFilePath $ (-<.> "html") . stripPathPrefix "tags"
compile $ do
let
ctx =
mconcat
[ listField "posts" postContext (metadataSort =<< loadAll posts)
, defaultContext
]
tagItem
>>= loadAndApplyTemplate "templates/tag.html" ctx
>>= applySiteLayout ctx
>>= normalizeUrls
match "frontend/dist/wp-*/**" $ do
route . routeAsFilePath $ stripPathPrefix "frontend/dist"
compile copyFileCompiler
match "templates/*" $ compile templateBodyCompiler
match "static/**" $ do
route . routeAsFilePath $ stripPathPrefix "static"
compile copyFileCompiler

View File

@ -1 +1,3 @@
/ /index.html 200
/:tag /:tag.html 200

4
tags/meta.md Normal file
View File

@ -0,0 +1,4 @@
---
title: Meta-Informationen zur Webseite
sort: -9001
---

View File

@ -7,13 +7,41 @@
$for(css)$
<link rel="stylesheet" href="$url$">
$endfor$
<title>UniWorX Systems</title>
<title>UniWorX Systems$if(title)$ - $title$$endif$</title>
</head>
<body>
<header>
<nav class="navbar navbar-expand-md navbar-dark bg-primary">
<button class="navbar-toggler collapsed" type="button" data-bs-toggle="collapse" data-bs-target="#navbarMain">
<span class="custom-navbar-toggler-icon"></span>
</button>
<a class="navbar-brand" href="/">
UniWorX Systems
</a>
<div class="collapse navbar-collapse" id="navbarMain">
<ul class="navbar-nav">
$for(tags-nav)$
$body$
$endfor$
</ul>
</div>
</nav>
</header>
<main>
$body$
</main>
<footer class="text-center">
<nav>
<ul>
$for(special-nav)$
<li>
<a href="$url$">$title$</a>
</li>
$endfor$
</ul>
</nav>
</footer>
$for(js)$
<script src="$url$"></script>
$endfor$

13
templates/tag-nav.html Normal file
View File

@ -0,0 +1,13 @@
<li class="nav-link dropdown">
<a class="nav-link dropdown-toggle" href="$route$" data-bs-toggle="dropdown";>
$title$
</a>
<ul class="dropdown-menu dropdown-menu-dark bg-primary">
$for(posts)$
<li class="dropdown-item">
<a class="nav-link" href="$route$#$identifier$">$title$</a>
</li>
$endfor$
</ul>
</li>

5
templates/tag.html Normal file
View File

@ -0,0 +1,5 @@
$for(posts)$
<article id="$identifier$">
$body$
</article>
$endfor$