Create CCCHH theme
This commit is contained in:
parent
8394b08524
commit
2d267ba9fe
40
README.md
40
README.md
|
@ -22,4 +22,42 @@ All other information like details on groups, projects and recurring events shou
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
TODO
|
### Build and Deploy
|
||||||
|
|
||||||
|
Running the hugo command without and parameters will re-generate the site in the `public` directory.
|
||||||
|
To deploy the website, just copy the whole folder to a directory which is servered by the webserver of your preference.
|
||||||
|
|
||||||
|
Please note, that the website should be re-deployed at least daily to update the "announcement" section on the front page even if there were no changed to the content.
|
||||||
|
|
||||||
|
### Add Pages
|
||||||
|
|
||||||
|
To run a local version, just install HUGO by following the [instructions](https://gohugo.io/installation/) for your operating system.
|
||||||
|
To build the website and run a development webserver, execute:
|
||||||
|
```shell
|
||||||
|
hugo server
|
||||||
|
```
|
||||||
|
|
||||||
|
To also build posts in the future or in draft state, run this instead:
|
||||||
|
```shell
|
||||||
|
hugo server -D
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Add an Event Announcement
|
||||||
|
|
||||||
|
There are two basic types of posts: Events and articles.
|
||||||
|
Events will be shown on the home page from their publishing date until they have happened.
|
||||||
|
|
||||||
|
To create a new event blog post, run a command like this:
|
||||||
|
```shell
|
||||||
|
hugo new content --king event blog/your-event-title.md
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Add a Blog Entry
|
||||||
|
|
||||||
|
As mentioned before, you can also create blog posts for things which aren't events.
|
||||||
|
They will only be shown in the "blog" section and posted to the RSS feeds.
|
||||||
|
|
||||||
|
To create a new general blog post, run a command like this:
|
||||||
|
```shell
|
||||||
|
hugo new content --king article blog/your-article-title.md
|
||||||
|
```
|
||||||
|
|
8
content/_index.md
Normal file
8
content/_index.md
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
---
|
||||||
|
title: "Home"
|
||||||
|
date: 2022-11-20T09:03:20-08:00
|
||||||
|
draft: false
|
||||||
|
---
|
||||||
|
TODO: Hallo, wir sind der CCC Hamburg...
|
||||||
|
|
||||||
|
TOOD: Was wir machen und wer wir sind
|
7
content/blog/_index.md
Normal file
7
content/blog/_index.md
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
---
|
||||||
|
title: "Blog"
|
||||||
|
draft: false
|
||||||
|
menu: main
|
||||||
|
---
|
||||||
|
|
||||||
|
TODO: Provide filters by type (announcement, post)
|
4
hugo.toml
Normal file
4
hugo.toml
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
baseURL = 'https://hamburg.ccc.de/'
|
||||||
|
languageCode = 'de-de'
|
||||||
|
title = 'CCC Hansestadt Hamburg e.V.'
|
||||||
|
theme = 'ccchh'
|
20
themes/ccchh/LICENSE
Normal file
20
themes/ccchh/LICENSE
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
The MIT License (MIT)
|
||||||
|
|
||||||
|
Copyright (c) 2023 YOUR_NAME_HERE
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||||
|
this software and associated documentation files (the "Software"), to deal in
|
||||||
|
the Software without restriction, including without limitation the rights to
|
||||||
|
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
|
||||||
|
the Software, and to permit persons to whom the Software is furnished to do so,
|
||||||
|
subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
|
||||||
|
FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
|
||||||
|
COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
|
||||||
|
IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||||
|
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
8
themes/ccchh/archetypes/article.md
Normal file
8
themes/ccchh/archetypes/article.md
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
---
|
||||||
|
kind: article
|
||||||
|
title: '{{ replace .File.ContentBaseName `-` ` ` | title }}'
|
||||||
|
date: '{{ .Date }}'
|
||||||
|
draft: true
|
||||||
|
---
|
||||||
|
|
||||||
|
TODO: Write your blog post
|
5
themes/ccchh/archetypes/default.md
Normal file
5
themes/ccchh/archetypes/default.md
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
---
|
||||||
|
title: "{{ replace .Name "-" " " | title }}"
|
||||||
|
date: {{ .Date }}
|
||||||
|
draft: true
|
||||||
|
---
|
9
themes/ccchh/archetypes/event.md
Normal file
9
themes/ccchh/archetypes/event.md
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
---
|
||||||
|
kind: event
|
||||||
|
title: '{{ replace .File.ContentBaseName `-` ` ` | title }}'
|
||||||
|
date: '{{ .Date }}' # date of the event
|
||||||
|
publishDate: '{{ .Date }}' # when to publish
|
||||||
|
draft: true
|
||||||
|
---
|
||||||
|
|
||||||
|
TODO: Describe your event here
|
59
themes/ccchh/assets/images/logo.svg
Normal file
59
themes/ccchh/assets/images/logo.svg
Normal file
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 86 KiB |
84
themes/ccchh/assets/js/roomstate.js
Normal file
84
themes/ccchh/assets/js/roomstate.js
Normal file
|
@ -0,0 +1,84 @@
|
||||||
|
import timeDistance, { deLocale } from 'js/util/timeDistance'
|
||||||
|
|
||||||
|
const spaceapiUrl = "https://www.hamburg.ccc.de/dooris/status.json"
|
||||||
|
const interval_ms = 60000
|
||||||
|
|
||||||
|
const classNameOpen = "open"
|
||||||
|
const classNameClosed = "closed"
|
||||||
|
|
||||||
|
|
||||||
|
function updateRoomState(openState, lastChangeTimestamp) {
|
||||||
|
console.debug("SpaceAPI: Setting room " + openState + " since " + lastChangeTimestamp)
|
||||||
|
|
||||||
|
const roomstate = document.querySelector('#roomstate')
|
||||||
|
var statusItem = roomstate.querySelector(".state")
|
||||||
|
var durationItem = roomstate.querySelector(".duration")
|
||||||
|
|
||||||
|
if (openState === null || lastChangeTimestamp === null) {
|
||||||
|
console.warn("SpaceAPI: Room state unknown");
|
||||||
|
statusItem.textContent = "unbekannt"
|
||||||
|
roomstate.classList.remove(classNameOpen)
|
||||||
|
roomstate.classList.remove(classNameClosed)
|
||||||
|
durationItem.textContent = "(seit unbekannt)"
|
||||||
|
|
||||||
|
} else {
|
||||||
|
if (openState) {
|
||||||
|
statusItem.textContent = "offen"
|
||||||
|
roomstate.classList.remove(classNameClosed)
|
||||||
|
roomstate.classList.add(classNameOpen)
|
||||||
|
|
||||||
|
} else {
|
||||||
|
statusItem.textContent = "geschlossen"
|
||||||
|
roomstate.classList.remove(classNameOpen)
|
||||||
|
roomstate.classList.add(classNameClosed)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
const changeDate = new Date(lastChangeTimestamp * 1000)
|
||||||
|
const changeText = timeDistance(deLocale).inWords(changeDate)
|
||||||
|
|
||||||
|
durationItem.textContent = "(" + changeText + ")"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function parseResponse(apiJson) {
|
||||||
|
console.debug('SpaceAPI got:', apiJson)
|
||||||
|
|
||||||
|
if (typeof apiJson.api === "undefined") {
|
||||||
|
console.error("SpaceAPI JSON invalid: 'api' item not present")
|
||||||
|
return [null, null]
|
||||||
|
}
|
||||||
|
if (typeof apiJson.state === "undefined") {
|
||||||
|
console.error("SpaceAPI JSON invalid: 'state' item not present")
|
||||||
|
return [null, null]
|
||||||
|
}
|
||||||
|
if (typeof apiJson.state.open === "undefined") {
|
||||||
|
console.error("SpaceAPI JSON invalid: 'state.open' item not present")
|
||||||
|
return [null, null]
|
||||||
|
}
|
||||||
|
|
||||||
|
console.debug('SpaceAPI state:', apiJson.state)
|
||||||
|
var openState = (apiJson.state.open == true)
|
||||||
|
var lastchange = null
|
||||||
|
|
||||||
|
if (apiJson.state.lastchange !== "undefined") {
|
||||||
|
lastchange = apiJson.state.lastchange
|
||||||
|
}
|
||||||
|
|
||||||
|
return [openState, lastchange]
|
||||||
|
}
|
||||||
|
|
||||||
|
function update() {
|
||||||
|
fetch(spaceapiUrl)
|
||||||
|
.then(resp => resp.json())
|
||||||
|
.then(function (data) {
|
||||||
|
var state = parseResponse(data)
|
||||||
|
updateRoomState(state[0], state[1])
|
||||||
|
})
|
||||||
|
.catch(err => { throw err });
|
||||||
|
}
|
||||||
|
|
||||||
|
window.onload = function () {
|
||||||
|
update()
|
||||||
|
window.setTimeout(update, interval_ms)
|
||||||
|
}
|
104
themes/ccchh/assets/js/util/timeDistance.js
Normal file
104
themes/ccchh/assets/js/util/timeDistance.js
Normal file
|
@ -0,0 +1,104 @@
|
||||||
|
export default ((locale) => {
|
||||||
|
const self = {}
|
||||||
|
|
||||||
|
if (locale === undefined) {
|
||||||
|
self.locales = {
|
||||||
|
pastPrefix: '',
|
||||||
|
pastSufix: 'ago',
|
||||||
|
|
||||||
|
futurePrefix: 'in',
|
||||||
|
futureSufix: '',
|
||||||
|
|
||||||
|
seconds: '%p less than a minutei %s',
|
||||||
|
minute: '%p about a minute %s',
|
||||||
|
minutes: '%p %d minutes %s',
|
||||||
|
hour: '%p about an hour %s',
|
||||||
|
hours: '%p about %d%r hours %s',
|
||||||
|
day: '%p a day %s',
|
||||||
|
days: '%p %d%r days %s',
|
||||||
|
month: '%p about a month %s',
|
||||||
|
months: '%p %d%r months %s',
|
||||||
|
year: '%p about a year %s',
|
||||||
|
years: '%p %d%r years %s'
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
self.locales = locale
|
||||||
|
}
|
||||||
|
|
||||||
|
self.inWords = (timeDistance, start) => {
|
||||||
|
if (start === undefined) {
|
||||||
|
start = new Date()
|
||||||
|
} else {
|
||||||
|
start = start instanceof(Date) ? start : parseInt(start)
|
||||||
|
}
|
||||||
|
timeDistance = timeDistance instanceof(Date) ? timeDistance : parseInt(timeDistance)
|
||||||
|
const prefix = timeDistance < new Date() ? self.locales.pastPrefix : self.locales.futurePrefix
|
||||||
|
const sufix = timeDistance < new Date() ? self.locales.pastSufix : self.locales.futureSufix
|
||||||
|
|
||||||
|
let seconds = Math.abs(Math.floor((start - timeDistance) / 1000)),
|
||||||
|
interval = 0,
|
||||||
|
rest = 0,
|
||||||
|
intervals = {
|
||||||
|
year: seconds / 31536000,
|
||||||
|
month: seconds / 2592000,
|
||||||
|
day: seconds / 86400,
|
||||||
|
hour: seconds / 3600,
|
||||||
|
minute: seconds / 60
|
||||||
|
}
|
||||||
|
|
||||||
|
let distance = self.locales.seconds
|
||||||
|
let key
|
||||||
|
|
||||||
|
for (key in intervals) {
|
||||||
|
interval = Math.floor(intervals[key])
|
||||||
|
rest = intervals[key] - interval
|
||||||
|
|
||||||
|
if (interval >= 1) {
|
||||||
|
distance = self.locales[key + 's']
|
||||||
|
break
|
||||||
|
} else if (interval === 1) {
|
||||||
|
distance = self.locales[key]
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rest > 0.5) {
|
||||||
|
distance = distance.replace(/%r/, "½")
|
||||||
|
} else if (rest > 0.25) {
|
||||||
|
distance = distance.replace(/%r/, "¼")
|
||||||
|
} else {
|
||||||
|
if (interval === 1) {
|
||||||
|
distance = self.locales[key]
|
||||||
|
}
|
||||||
|
distance = distance.replace(/\s*%r/, "")
|
||||||
|
}
|
||||||
|
|
||||||
|
distance = distance.replace(/%d/i, interval)
|
||||||
|
distance = distance.replace(/%p/i, prefix)
|
||||||
|
distance = distance.replace(/%s/i, sufix)
|
||||||
|
|
||||||
|
return distance.trim()
|
||||||
|
}
|
||||||
|
|
||||||
|
return self
|
||||||
|
})
|
||||||
|
|
||||||
|
export const deLocale = {
|
||||||
|
pastPrefix: 'seit',
|
||||||
|
pastSufix: '',
|
||||||
|
|
||||||
|
futurePrefix: 'in',
|
||||||
|
futureSufix: '',
|
||||||
|
|
||||||
|
seconds: '%p %d Sekunden',
|
||||||
|
minute: '%p einer Minute',
|
||||||
|
minutes: '%p %d Minuten',
|
||||||
|
hour: '%p einer Stunde',
|
||||||
|
hours: '%p %d%r Stunden',
|
||||||
|
day: '%p einem Tag',
|
||||||
|
days: '%p %d%r Tagen',
|
||||||
|
month: '%p einem Monat',
|
||||||
|
months: '%p %d%r Monaten',
|
||||||
|
year: '%p einem Jahr',
|
||||||
|
years: '%p %d%r Jahren'
|
||||||
|
}
|
78
themes/ccchh/assets/sass/main.scss
Normal file
78
themes/ccchh/assets/sass/main.scss
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
$roomstate_color_unknown: #dda218;
|
||||||
|
$roomstate_color_open: var(--ins-color);
|
||||||
|
$roomstate_color_closed: var(--del-color);
|
||||||
|
|
||||||
|
|
||||||
|
// Room State in Menu
|
||||||
|
#roomstate {
|
||||||
|
font-size: 0.9em;
|
||||||
|
line-height: 1.0em;
|
||||||
|
max-width: 8em;
|
||||||
|
padding: 5px;
|
||||||
|
|
||||||
|
color: $roomstate_color_unknown;
|
||||||
|
|
||||||
|
&.open {
|
||||||
|
color: $roomstate_color_open;
|
||||||
|
}
|
||||||
|
|
||||||
|
&.closed {
|
||||||
|
color: $roomstate_color_closed;
|
||||||
|
}
|
||||||
|
|
||||||
|
span.duration {
|
||||||
|
font-size: 0.7em;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// CCCHH Icon in Menu
|
||||||
|
@media only screen and (prefers-color-scheme: light) {
|
||||||
|
.invert-on-light {
|
||||||
|
filter: invert(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Home page Announcements
|
||||||
|
.announcement {
|
||||||
|
border-radius: var(--border-radius);
|
||||||
|
background: var(--code-background-color);
|
||||||
|
padding: 10px 15px;
|
||||||
|
|
||||||
|
margin-bottom: var(--typography-spacing-vertical);
|
||||||
|
|
||||||
|
p:last-child {
|
||||||
|
margin-bottom: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@media only screen and (prefers-color-scheme: dark) {
|
||||||
|
.announcement {
|
||||||
|
background: var(--code-background-color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Home Friends&Family Gallery
|
||||||
|
.flex-grid {
|
||||||
|
display: flex;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
justify-content: center;
|
||||||
|
|
||||||
|
div {
|
||||||
|
width: 250px;
|
||||||
|
|
||||||
|
// 2*250px + 2*var(--spacing) + 1px
|
||||||
|
@media only screen and (max-width: 533px) {
|
||||||
|
width: 150px;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.img-link {
|
||||||
|
a {
|
||||||
|
img {
|
||||||
|
display: block;
|
||||||
|
padding: var(--grid-spacing-horizontal);
|
||||||
|
margin: 0 auto;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
1
themes/ccchh/hugo.toml
Normal file
1
themes/ccchh/hugo.toml
Normal file
|
@ -0,0 +1 @@
|
||||||
|
# Theme config.
|
8
themes/ccchh/layouts/404.html
Normal file
8
themes/ccchh/layouts/404.html
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
{{ define "main" }}
|
||||||
|
<main class="container" aria-role="main">
|
||||||
|
<div>
|
||||||
|
<h1 id="title">404 Page not Found</h1>
|
||||||
|
<a href="{{ "" | relURL }}">Back Home</a>
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
{{ end }}
|
12
themes/ccchh/layouts/_default/baseof.html
Normal file
12
themes/ccchh/layouts/_default/baseof.html
Normal file
|
@ -0,0 +1,12 @@
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
{{- partial "head.html" . }}
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
{{- partial "header.html" . }}
|
||||||
|
{{- block "main" . }}{{- end }}
|
||||||
|
{{- partial "footer.html" . }}
|
||||||
|
</body>
|
||||||
|
</html>
|
13
themes/ccchh/layouts/_default/single.html
Normal file
13
themes/ccchh/layouts/_default/single.html
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
{{ define "main" }}
|
||||||
|
<main class="container" aria-role="main">
|
||||||
|
<header class="header">
|
||||||
|
<h1>{{ .Title }}</h1>
|
||||||
|
{{ with .Params.subtitle }}
|
||||||
|
<span class="subtitle">{{ . }}</span>
|
||||||
|
{{ end }}
|
||||||
|
</header>
|
||||||
|
<div class="content">
|
||||||
|
{{ .Content }}
|
||||||
|
</div>
|
||||||
|
</main>
|
||||||
|
{{ end }}
|
33
themes/ccchh/layouts/blog/list.html
Normal file
33
themes/ccchh/layouts/blog/list.html
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
{{ define "main" }}
|
||||||
|
<main class="container" aria-role="main">
|
||||||
|
<header class="header">
|
||||||
|
<h1>{{ .Title }}</h1>
|
||||||
|
{{ with .Params.subtitle }}
|
||||||
|
<span class="subtitle">{{ . }}</span>
|
||||||
|
{{ end }}
|
||||||
|
</header>
|
||||||
|
<div class="content">
|
||||||
|
{{ .Content }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
{{ range .Pages }}
|
||||||
|
<li>
|
||||||
|
<a href="{{ .Permalink }}">{{ .Date.Format "2006-01-02" }} | {{ .Title }}</a>
|
||||||
|
</li>
|
||||||
|
{{ end }}
|
||||||
|
</ul>
|
||||||
|
|
||||||
|
{{ range .Pages.GroupByParam "kind" }}
|
||||||
|
<h3>{{ .Key }}</h3>
|
||||||
|
<ul>
|
||||||
|
{{ range .Pages }}
|
||||||
|
<li>
|
||||||
|
<a href="{{ .Permalink }}">{{ .Date.Format "2006-01-02" }} | {{ .Title }}</a>
|
||||||
|
</li>
|
||||||
|
{{ end }}
|
||||||
|
</ul>
|
||||||
|
{{ end }}
|
||||||
|
<!-- TODO: Pagination: see https://gohugo.io/templates/pagination/ -->
|
||||||
|
</main>
|
||||||
|
{{ end }}
|
50
themes/ccchh/layouts/index.html
Normal file
50
themes/ccchh/layouts/index.html
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
{{ define "main" }}
|
||||||
|
<main class="container" aria-role="main">
|
||||||
|
<!-- <header class="homepage-header">
|
||||||
|
<h1>{{ .Title }}</h1>
|
||||||
|
{{ with .Params.subtitle }}
|
||||||
|
<span class="subtitle">{{ . }}</span>
|
||||||
|
{{ end }}
|
||||||
|
</header> -->
|
||||||
|
<div class="homepage-content">
|
||||||
|
<!-- Note that the content for index.html, as a sort of list page, will pull from content/_index.md -->
|
||||||
|
{{ .Content }}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
{{- $events := where (.Site.GetPage "blog").Pages ".Params.kind" "event" }}
|
||||||
|
{{- $upcoming := where $events ".Params.date" "ge" now }}
|
||||||
|
{{ if $upcoming}}
|
||||||
|
<div class="announcements">
|
||||||
|
<h3>Neuigkeiten</h3>
|
||||||
|
{{- range $upcoming.ByDate }}
|
||||||
|
<div class="announcement">
|
||||||
|
<p><a href="{{ .Permalink }}">{{ .Date.Format "2006-01-02" }}: {{ .Title }}</a>
|
||||||
|
{{ .Summary }}
|
||||||
|
{{- if .Truncated }}
|
||||||
|
<a href="{{ .RelPermalink }}">Read More…</a>
|
||||||
|
{{- end }}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
{{- end }}
|
||||||
|
</div>
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{- $home_sections := .Site.GetPage "/home" }}
|
||||||
|
{{- range sort ($home_sections.Resources.Match "*.md") ".Name" }}
|
||||||
|
<div class="section">
|
||||||
|
<h3>{{ .Title }}</h3>
|
||||||
|
{{ .Content -}}
|
||||||
|
|
||||||
|
{{- with .Params.Resources }}
|
||||||
|
<div class="flex-grid">
|
||||||
|
{{- range . }}
|
||||||
|
{{- $img := $home_sections.Resources.GetMatch (printf "%s" .src) }}
|
||||||
|
<div class="img-link"><a href="{{ .params.url }}"><img src="{{ $img.Permalink }}" class="box-image" alt=""></a></div>
|
||||||
|
{{- end }}
|
||||||
|
</div>
|
||||||
|
{{- end }}
|
||||||
|
</div>
|
||||||
|
{{ end }}
|
||||||
|
|
||||||
|
</main>
|
||||||
|
{{ end }}
|
6
themes/ccchh/layouts/partials/footer.html
Normal file
6
themes/ccchh/layouts/partials/footer.html
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
|
||||||
|
<footer class="container">
|
||||||
|
<nav class="menu">
|
||||||
|
{{- partial "menu.html" (dict "menuID" "footer" "page" . ) -}}
|
||||||
|
</nav>
|
||||||
|
</footer>
|
22
themes/ccchh/layouts/partials/head.html
Normal file
22
themes/ccchh/layouts/partials/head.html
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
{{- $options := dict "transpiler" "libsass" "targetPath" "css/style.css" -}}
|
||||||
|
|
||||||
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
|
<meta charset="utf-8">
|
||||||
|
{{- with resources.GetRemote "https://cdn.jsdelivr.net/npm/@picocss/pico@1/css/pico.min.css" }}
|
||||||
|
<link rel="stylesheet" href="{{ .RelPermalink }}" crossorigin="anonymous">
|
||||||
|
{{ end }}
|
||||||
|
{{ with resources.Get "sass/main.scss" | toCSS $options | minify | fingerprint -}}
|
||||||
|
<link rel="stylesheet" href="{{ .RelPermalink }}" integrity="{{ .Data.Integrity }}" crossorigin="anonymous">
|
||||||
|
{{- end }}
|
||||||
|
<link rel="stylesheet" href="{{ .Site.BaseURL }}thirdparty/fontawesome6/css/all.min.css" crossorigin="anonymous">
|
||||||
|
|
||||||
|
{{ with resources.Get "js/roomstate.js" | js.Build | minify | fingerprint -}}
|
||||||
|
<script src="{{ .RelPermalink }}" integrity="{{ .Data.Integrity }}" crossorigin="anonymous"></script>
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
{{ range .AlternativeOutputFormats -}}
|
||||||
|
{{ printf `<link rel="%s" type="%s" href="%s" title="%s" />` .Rel .MediaType.Type .Permalink $.Site.Title | safeHTML }}
|
||||||
|
{{ end -}}
|
||||||
|
|
||||||
|
<title>{{ .Title }}</title>
|
||||||
|
<!-- TODO: Favicon -->
|
6
themes/ccchh/layouts/partials/header.html
Normal file
6
themes/ccchh/layouts/partials/header.html
Normal file
|
@ -0,0 +1,6 @@
|
||||||
|
|
||||||
|
<div class="container header">
|
||||||
|
<nav class="menu">
|
||||||
|
{{- partial "menu.html" (dict "menuID" "main" "page" . ) -}}
|
||||||
|
</nav>
|
||||||
|
</div>
|
32
themes/ccchh/layouts/partials/menu.html
Normal file
32
themes/ccchh/layouts/partials/menu.html
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
{{- $page := .page -}}
|
||||||
|
{{- $menuID := .menuID -}}
|
||||||
|
{{- $menuContent := index site.Menus .menuID -}}
|
||||||
|
|
||||||
|
<ul>
|
||||||
|
{{- if compare.Eq $menuID "main" -}}
|
||||||
|
{{ $image := resources.Get "images/logo.svg" }}
|
||||||
|
<li><a href="/{{ .Site.Home.URL }}"><img src="{{ $image.RelPermalink }}" class="invert-on-light" width="150px" alt="CCCHH Icon"></a></li>
|
||||||
|
{{- end }}
|
||||||
|
{{- range $menuContent }}
|
||||||
|
<li>
|
||||||
|
{{- $attrs := dict "href" .URL }}
|
||||||
|
{{- if $page.IsMenuCurrent $menuID . -}}
|
||||||
|
{{- $attrs = merge $attrs (dict "class" "active" "aria-current" "page") }}
|
||||||
|
{{- end -}}
|
||||||
|
<a
|
||||||
|
{{- range $k, $v := $attrs }}
|
||||||
|
{{- with $v }}
|
||||||
|
{{- printf " %s=%q" $k $v | safeHTMLAttr }}
|
||||||
|
{{- end }}
|
||||||
|
{{- end -}}
|
||||||
|
>{{ or (T .Identifier) .Name | safeHTML }}</a></li>
|
||||||
|
{{- end }}
|
||||||
|
|
||||||
|
</ul>
|
||||||
|
{{- if compare.Eq $menuID "main" -}}
|
||||||
|
<ul>
|
||||||
|
<li class="roomstate" id="roomstate">
|
||||||
|
<span class="state">unbekannt</span><br><span class="duration">(seit )</span>
|
||||||
|
</li>
|
||||||
|
</ul>
|
||||||
|
{{- end }}
|
21
themes/ccchh/theme.toml
Normal file
21
themes/ccchh/theme.toml
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
# theme.toml template for a Hugo theme
|
||||||
|
# See https://github.com/gohugoio/hugoThemes#themetoml for an example
|
||||||
|
|
||||||
|
name = "CCCHH"
|
||||||
|
license = "MIT"
|
||||||
|
licenselink = "https://github.com/yourname/yourtheme/blob/master/LICENSE"
|
||||||
|
description = ""
|
||||||
|
# homepage = "http://example.com/"
|
||||||
|
tags = []
|
||||||
|
features = []
|
||||||
|
min_version = "0.114.1"
|
||||||
|
|
||||||
|
[author]
|
||||||
|
name = ""
|
||||||
|
homepage = ""
|
||||||
|
|
||||||
|
# If porting an existing theme
|
||||||
|
[original]
|
||||||
|
name = ""
|
||||||
|
homepage = ""
|
||||||
|
repo = ""
|
Loading…
Reference in a new issue