Compare commits

..

No commits in common. "2b0901a98209f1963377e8baa6cc73c737c03c01" and "26a9dc1e03ebce1ec2cb8176034b4e8c4220e5b8" have entirely different histories.

160 changed files with 37 additions and 504 deletions

View file

@ -1,46 +0,0 @@
root = "."
testdata_dir = "testdata"
tmp_dir = "tmp"
[build]
args_bin = []
bin = "./www"
cmd = "make webserver"
delay = 1000
exclude_dir = ["hugo", "tmp", "vendor"]
exclude_file = []
exclude_regex = ["_test.go", ".*_templ.go"]
exclude_unchanged = false
follow_symlink = false
full_bin = "PORT=8080 HOST=127.0.0.1 DEBUG=true ./www"
include_dir = []
include_ext = ["go", "tpl", "tmpl", "html", "templ", "toml"]
include_file = []
kill_delay = "0s"
log = "build-errors.log"
poll = false
poll_interval = 0
post_cmd = []
pre_cmd = []
rerun = false
rerun_delay = 500
send_interrupt = false
stop_on_error = false
[color]
app = ""
build = "yellow"
main = "magenta"
runner = "green"
watcher = "cyan"
[log]
main_only = false
time = false
[misc]
clean_on_exit = false
[screen]
clear_on_rebuild = false
keep_scroll = true

2
.gitignore vendored
View file

@ -2,5 +2,3 @@
public/ public/
resources/ resources/
app app
www

View file

@ -1,4 +1,4 @@
FROM docker.io/library/golang:alpine AS builder FROM golang:alpine AS builder
RUN apk update \ RUN apk update \
&& apk add --no-cache git \ && apk add --no-cache git \
&& apk add --no-cache --repository=https://dl-cdn.alpinelinux.org/alpine/edge/community hugo && apk add --no-cache --repository=https://dl-cdn.alpinelinux.org/alpine/edge/community hugo
@ -6,7 +6,7 @@ RUN apk update \
WORKDIR $GOPATH/src/www-jmbit-de WORKDIR $GOPATH/src/www-jmbit-de
COPY . . COPY . .
RUN go get -d -v RUN go get -d -v
RUN cd hugo && hugo RUN hugo --minify
RUN go build -a -installsuffix cgo -ldflags="-w -s" -o /go/bin/www RUN go build -a -installsuffix cgo -ldflags="-w -s" -o /go/bin/www
FROM scratch FROM scratch

View file

@ -4,14 +4,13 @@ CTNAME:=git.jmbit.de/jmb/www-jmbit-de
all: hugo webserver all: hugo webserver
dev: dev:
cd hugo && hugo server -D hugo server -D
hugo: hugo:
cd hugo && hugo hugo
webserver: webserver:
templ generate . CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o app .
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o www .
container: container:
podman build -t $(CTNAME):latest -t $(CTNAME):$(HEAD) . podman build -t $(CTNAME):latest -t $(CTNAME):$(HEAD) .
@ -20,7 +19,5 @@ run:
podman run --rm -p8080:80 $(CTNAME) podman run --rm -p8080:80 $(CTNAME)
clean: clean:
rm -rf hugo/public rm -rf public
rm -f www
.PHONY: all dev hugo webserver container run clean

View file

2
go.mod
View file

@ -1,5 +1,3 @@
module git.jmbit.de/jmb/www-jmbit-de module git.jmbit.de/jmb/www-jmbit-de
go 1.21.5 go 1.21.5
require github.com/a-h/templ v0.2.793 // indirect

2
go.sum
View file

@ -1,2 +0,0 @@
github.com/a-h/templ v0.2.793 h1:Io+/ocnfGWYO4VHdR0zBbf39PQlnzVCVVD+wEEs6/qY=
github.com/a-h/templ v0.2.793/go.mod h1:lq48JXoUvuQrU0VThrK31yFwdRjTCnIE5bcPCM9IP1w=

View file

@ -1,8 +0,0 @@
package hugo
import (
"embed"
)
//go:embed public/*
var PublicFS embed.FS

File diff suppressed because one or more lines are too long

Binary file not shown.

View file

@ -1,47 +0,0 @@
package config
import (
"log"
"os"
"strconv"
)
type Config struct {
Host string
Port int
Debug bool
}
func GetConfig() (*Config, error) {
config := &Config{}
if os.Getenv("HOST") != "" {
config.Host = os.Getenv("HOST")
} else {
config.Host = "0.0.0.0"
}
if os.Getenv("PORT") != "" {
port := os.Getenv("PORT")
var err error
config.Port, err = strconv.Atoi(port)
if err != nil {
log.Fatal(err)
}
} else {
config.Port = 80
}
if os.Getenv("DEBUG") != "" {
debug := os.Getenv("DEBUG")
var err error
config.Debug, err = strconv.ParseBool(debug)
if err != nil {
log.Fatal(err)
}
} else {
config.Debug = false
}
return config, nil
}

View file

@ -1,12 +0,0 @@
package middlewares
import (
"net/http"
)
func Caching(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Cache-Control", "max-age=3600")
next.ServeHTTP(w, r)
})
}

View file

@ -1,32 +0,0 @@
package middlewares
import (
"log"
"net/http"
"time"
)
type wrappedWriter struct {
http.ResponseWriter
statusCode int
}
func (w *wrappedWriter) WriteHeader(statusCode int) {
w.ResponseWriter.WriteHeader(statusCode)
w.statusCode = statusCode
}
func Logging(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
start := time.Now()
wrapped := &wrappedWriter{
ResponseWriter: w,
statusCode: http.StatusOK,
}
next.ServeHTTP(wrapped, r)
log.Println(wrapped.statusCode, r.Method, r.URL.Path, r.RemoteAddr, time.Since(start))
})
}

View file

@ -1,16 +0,0 @@
package middlewares
import "net/http"
type Middleware func(http.Handler) http.Handler
func CreateStack(xs ...Middleware) Middleware {
return func(next http.Handler) http.Handler {
for i := len(xs) - 1; i >= 0; i-- {
x := xs[i]
next = x(next)
}
return next
}
}

View file

@ -1,12 +0,0 @@
package middlewares
import (
"net/http"
)
func TerryPratchet(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Header().Set("X-Clacks-Overhead", "Terry Pratchett")
next.ServeHTTP(w, r)
})
}

View file

@ -1,16 +0,0 @@
package server
import (
"net/http"
"git.jmbit.de/jmb/www-jmbit-de/internal/web"
)
// RegisterRoutes registers all the routes
func RegisterRoutes() *http.ServeMux {
mux := http.NewServeMux()
mux.HandleFunc("/tools/", web.ToolsWebHandler)
mux.HandleFunc("/", web.HugoWebHandler)
return mux
}

View file

@ -1,34 +0,0 @@
package server
import (
"fmt"
"git.jmbit.de/jmb/www-jmbit-de/internal/middlewares"
"log"
"net/http"
"time"
)
func NewServer(host string, port int, logging bool) *http.Server {
middlewareStack := middlewares.CreateStack()
if logging {
log.Println("Enabling HTTP logging")
middlewareStack = middlewares.CreateStack(
middlewares.Logging,
middlewares.TerryPratchet,
)
} else {
middlewareStack = middlewares.CreateStack(
middlewares.TerryPratchet,
)
}
server := &http.Server{
Addr: fmt.Sprintf("%s:%d", host, port),
Handler: middlewareStack(RegisterRoutes()),
IdleTimeout: time.Minute,
ReadTimeout: 10 * time.Second,
WriteTimeout: 30 * time.Second,
}
return server
}

View file

@ -1,76 +0,0 @@
package web
templ Base(title string) {
<!doctype html>
<html lang="de">
<head>
<title>{title}</title>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width,initial-scale=1"/>
<meta name="description" content="Consulting & Support zu IT-Sicherheit, Linux, Hosting, Entwicklung und mehr">
<meta name="keywords" content="linux,it,consulting,security,hosting,development,jmbit,johannes bülow">
<meta name="robots" content="noodp">
<link rel="stylesheet" href="/themestyles.css">
<link rel="stylesheet" href="https://www.jmbit.de/terminal.css">
<link rel="shortcut icon" href="https://www.jmbit.de/favicon.png">
<link rel="apple-touch-icon" href="https://www.jmbit.de/apple-touch-icon.png">
<meta name="twitter:card" content="summary">
<meta property="og:locale" content="de">
<meta property="og:type" content="website">
<meta property="og:title" content>
<meta property="og:description" content="Consulting & Support zu IT-Sicherheit, Linux, Hosting, Entwicklung und mehr">
<meta property="og:url" content="https://www.jmbit.de/">
<meta property="og:site_name" content>
<meta property="og:image" content="https://www.jmbit.de/og-image.png">
<meta property="og:image:width" content="1200">
<meta property="og:image:height" content="627">
<link href="/index.xml" rel="alternate" type="application/rss+xml" title>
</head>
<body>
<div class="container center">
<header class="header">
<div class="header__inner">
<div class="header__logo">
<a href="/">
<div class="logo">JMB IT</div>
</a>
</div>
<ul class="menu menu--mobile">
<li class="menu__trigger">Menu&nbsp;▾</li>
<li>
<ul class="menu__dropdown">
<li><a href="/blog/">Blog</a></li>
<li><a href="/consulting/">Consulting</a></li>
<li><a href="/expertise.html">Expertise</a></li>
<li><a href="/tools/">Tools</a></li>
<li><a href="/about/">Über mich</a></li>
</ul>
</li>
</ul>
</div>
<nav class="navigation-menu">
<ul class="navigation-menu__inner menu--desktop">
<li><a href="/blog/">Blog</a></li>
<li><a href="/consulting/">Consulting</a></li>
<li><a href="/expertise.html">Expertise</a></li>
<li><a href="/tools/">Tools</a></li>
<li><a href="/about/">Über mich</a></li>
</ul>
</nav>
</header>
<div class="content">
{ children... }
</div>
<footer class="footer">
<div class="footer__inner">
<div class="copyright"><span>© 2024 Johannes Bülow :: Powered by <a href="http://gohugo.io">Hugo</a></span>
<span>:: <a href="/impressum/index.html">Impressum</a></span>
<span>:: <a href="https://github.com/panr/hugo-theme-terminal" target="_blank">Theme</a> made by <a href="https://github.com/panr" target="_blank">panr</a></span>
</div>
</div>
</footer>
<script type="text/javascript" src="/bundle.min.js"></script>
</div>
</body>
</html>
}

View file

@ -1,61 +0,0 @@
// Code generated by templ - DO NOT EDIT.
// templ: version: v0.2.793
package web
//lint:file-ignore SA4006 This context is only used if a nested component is present.
import "github.com/a-h/templ"
import templruntime "github.com/a-h/templ/runtime"
func Base(title string) templ.Component {
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
return templ_7745c5c3_CtxErr
}
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
if !templ_7745c5c3_IsBuffer {
defer func() {
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
if templ_7745c5c3_Err == nil {
templ_7745c5c3_Err = templ_7745c5c3_BufErr
}
}()
}
ctx = templ.InitializeContext(ctx)
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
if templ_7745c5c3_Var1 == nil {
templ_7745c5c3_Var1 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<!doctype html><html lang=\"de\"><head><title>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
var templ_7745c5c3_Var2 string
templ_7745c5c3_Var2, templ_7745c5c3_Err = templ.JoinStringErrs(title)
if templ_7745c5c3_Err != nil {
return templ.Error{Err: templ_7745c5c3_Err, FileName: `internal/web/base.templ`, Line: 7, Col: 19}
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString(templ.EscapeString(templ_7745c5c3_Var2))
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</title><meta charset=\"utf-8\"><meta name=\"viewport\" content=\"width=device-width,initial-scale=1\"><meta name=\"description\" content=\"Consulting &amp; Support zu IT-Sicherheit, Linux, Hosting, Entwicklung und mehr\"><meta name=\"keywords\" content=\"linux,it,consulting,security,hosting,development,jmbit,johannes bülow\"><meta name=\"robots\" content=\"noodp\"><link rel=\"stylesheet\" href=\"/themestyles.css\"><link rel=\"stylesheet\" href=\"https://www.jmbit.de/terminal.css\"><link rel=\"shortcut icon\" href=\"https://www.jmbit.de/favicon.png\"><link rel=\"apple-touch-icon\" href=\"https://www.jmbit.de/apple-touch-icon.png\"><meta name=\"twitter:card\" content=\"summary\"><meta property=\"og:locale\" content=\"de\"><meta property=\"og:type\" content=\"website\"><meta property=\"og:title\" content><meta property=\"og:description\" content=\"Consulting &amp; Support zu IT-Sicherheit, Linux, Hosting, Entwicklung und mehr\"><meta property=\"og:url\" content=\"https://www.jmbit.de/\"><meta property=\"og:site_name\" content><meta property=\"og:image\" content=\"https://www.jmbit.de/og-image.png\"><meta property=\"og:image:width\" content=\"1200\"><meta property=\"og:image:height\" content=\"627\"><link href=\"/index.xml\" rel=\"alternate\" type=\"application/rss+xml\" title></head><body><div class=\"container center\"><header class=\"header\"><div class=\"header__inner\"><div class=\"header__logo\"><a href=\"/\"><div class=\"logo\">JMB IT</div></a></div><ul class=\"menu menu--mobile\"><li class=\"menu__trigger\">Menu&nbsp;▾</li><li><ul class=\"menu__dropdown\"><li><a href=\"/blog/\">Blog</a></li><li><a href=\"/consulting/\">Consulting</a></li><li><a href=\"/expertise.html\">Expertise</a></li><li><a href=\"/tools/\">Tools</a></li><li><a href=\"/about/\">Über mich</a></li></ul></li></ul></div><nav class=\"navigation-menu\"><ul class=\"navigation-menu__inner menu--desktop\"><li><a href=\"/blog/\">Blog</a></li><li><a href=\"/consulting/\">Consulting</a></li><li><a href=\"/expertise.html\">Expertise</a></li><li><a href=\"/tools/\">Tools</a></li><li><a href=\"/about/\">Über mich</a></li></ul></nav></header><div class=\"content\">")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
templ_7745c5c3_Err = templ_7745c5c3_Var1.Render(ctx, templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("</div><footer class=\"footer\"><div class=\"footer__inner\"><div class=\"copyright\"><span>© 2024 Johannes Bülow :: Powered by <a href=\"http://gohugo.io\">Hugo</a></span> <span>:: <a href=\"/impressum/index.html\">Impressum</a></span> <span>:: <a href=\"https://github.com/panr/hugo-theme-terminal\" target=\"_blank\">Theme</a> made by <a href=\"https://github.com/panr\" target=\"_blank\">panr</a></span></div></div></footer><script type=\"text/javascript\" src=\"/bundle.min.js\"></script></div></body></html>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
return templ_7745c5c3_Err
})
}
var _ = templruntime.GeneratedTemplate

View file

@ -1,18 +0,0 @@
package web
import (
"io/fs"
"net/http"
"git.jmbit.de/jmb/www-jmbit-de/hugo"
)
func HugoWebHandler(w http.ResponseWriter, r *http.Request) {
fsroot, err := fs.Sub(hugo.PublicFS, "public")
if err != nil {
panic(err)
}
w.Header().Set("Cache-Control", "max-age=3600")
http.FileServer(http.FS(fsroot)).ServeHTTP(w, r)
}

View file

@ -1,18 +0,0 @@
package web
import (
"net/http"
"log"
)
func ToolsWebHandler(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "text/html; charset=utf-8")
component := Tools()
err := component.Render(r.Context(), w)
if err != nil {
http.Error(w, err.Error(), http.StatusBadRequest)
log.Printf("Error rendering in ToolsWebHandler: %e", err)
}
}

View file

@ -1,17 +0,0 @@
package web
templ Tools() {
@Base("Tools") {
<article class="post">
<h1 class="post-title">
<a href="/tools/">Tools</a> <a href="#tools" class="hanchor" ariaLabel="Anchor">#</a>
</h1>
<div class="post-meta"></div>
<div class="post-content"><div>
<p>Sammlung von selbst-programmierten tools</p>
<p>Gähnende Leere</p>
</div>
</div>
</article>
}
}

View file

@ -1,58 +0,0 @@
// Code generated by templ - DO NOT EDIT.
// templ: version: v0.2.793
package web
//lint:file-ignore SA4006 This context is only used if a nested component is present.
import "github.com/a-h/templ"
import templruntime "github.com/a-h/templ/runtime"
func Tools() templ.Component {
return templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
if templ_7745c5c3_CtxErr := ctx.Err(); templ_7745c5c3_CtxErr != nil {
return templ_7745c5c3_CtxErr
}
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
if !templ_7745c5c3_IsBuffer {
defer func() {
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
if templ_7745c5c3_Err == nil {
templ_7745c5c3_Err = templ_7745c5c3_BufErr
}
}()
}
ctx = templ.InitializeContext(ctx)
templ_7745c5c3_Var1 := templ.GetChildren(ctx)
if templ_7745c5c3_Var1 == nil {
templ_7745c5c3_Var1 = templ.NopComponent
}
ctx = templ.ClearChildren(ctx)
templ_7745c5c3_Var2 := templruntime.GeneratedTemplate(func(templ_7745c5c3_Input templruntime.GeneratedComponentInput) (templ_7745c5c3_Err error) {
templ_7745c5c3_W, ctx := templ_7745c5c3_Input.Writer, templ_7745c5c3_Input.Context
templ_7745c5c3_Buffer, templ_7745c5c3_IsBuffer := templruntime.GetBuffer(templ_7745c5c3_W)
if !templ_7745c5c3_IsBuffer {
defer func() {
templ_7745c5c3_BufErr := templruntime.ReleaseBuffer(templ_7745c5c3_Buffer)
if templ_7745c5c3_Err == nil {
templ_7745c5c3_Err = templ_7745c5c3_BufErr
}
}()
}
ctx = templ.InitializeContext(ctx)
_, templ_7745c5c3_Err = templ_7745c5c3_Buffer.WriteString("<article class=\"post\"><h1 class=\"post-title\"><a href=\"/tools/\">Tools</a> <a href=\"#tools\" class=\"hanchor\" ariaLabel=\"Anchor\">#</a></h1><div class=\"post-meta\"></div><div class=\"post-content\"><div><p>Sammlung von selbst-programmierten tools</p><p>Gähnende Leere</p></div></div></article>")
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
return templ_7745c5c3_Err
})
templ_7745c5c3_Err = Base("Tools").Render(templ.WithChildren(ctx, templ_7745c5c3_Var2), templ_7745c5c3_Buffer)
if templ_7745c5c3_Err != nil {
return templ_7745c5c3_Err
}
return templ_7745c5c3_Err
})
}
var _ = templruntime.GeneratedTemplate

16
main.go
View file

@ -1,16 +0,0 @@
package main
import (
"git.jmbit.de/jmb/www-jmbit-de/internal/config"
"git.jmbit.de/jmb/www-jmbit-de/internal/server"
)
func main() {
config, err := config.GetConfig()
if err != nil {
panic(err)
}
server := server.NewServer(config.Host, config.Port, config.Debug)
server.ListenAndServe()
}

31
server.go Normal file
View file

@ -0,0 +1,31 @@
package main
import (
"embed"
"io/fs"
"log"
"net/http"
)
//go:embed public/*
var publicFS embed.FS
func main() {
// Register a custom handler
http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
fsroot, err := fs.Sub(publicFS, "public")
if err != nil {
panic(err)
}
http.FileServer(http.FS(fsroot)).ServeHTTP(w,r)
})
// Start the HTTP server on port 80
err := http.ListenAndServe(":80", nil)
if err != nil {
log.Fatal(err)
}
}

View file

Before

Width:  |  Height:  |  Size: 207 B

After

Width:  |  Height:  |  Size: 207 B

View file

Before

Width:  |  Height:  |  Size: 207 B

After

Width:  |  Height:  |  Size: 207 B

View file

Before

Width:  |  Height:  |  Size: 228 KiB

After

Width:  |  Height:  |  Size: 228 KiB

View file

Before

Width:  |  Height:  |  Size: 122 KiB

After

Width:  |  Height:  |  Size: 122 KiB

View file

Before

Width:  |  Height:  |  Size: 190 KiB

After

Width:  |  Height:  |  Size: 190 KiB

View file

Before

Width:  |  Height:  |  Size: 189 KiB

After

Width:  |  Height:  |  Size: 189 KiB

View file

Before

Width:  |  Height:  |  Size: 112 KiB

After

Width:  |  Height:  |  Size: 112 KiB

View file

Before

Width:  |  Height:  |  Size: 227 KiB

After

Width:  |  Height:  |  Size: 227 KiB

View file

Before

Width:  |  Height:  |  Size: 308 KiB

After

Width:  |  Height:  |  Size: 308 KiB

View file

Before

Width:  |  Height:  |  Size: 63 KiB

After

Width:  |  Height:  |  Size: 63 KiB

View file

Before

Width:  |  Height:  |  Size: 416 KiB

After

Width:  |  Height:  |  Size: 416 KiB

View file

Before

Width:  |  Height:  |  Size: 45 KiB

After

Width:  |  Height:  |  Size: 45 KiB

View file

Before

Width:  |  Height:  |  Size: 291 KiB

After

Width:  |  Height:  |  Size: 291 KiB

View file

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 14 KiB

View file

Before

Width:  |  Height:  |  Size: 84 KiB

After

Width:  |  Height:  |  Size: 84 KiB

View file

Before

Width:  |  Height:  |  Size: 68 KiB

After

Width:  |  Height:  |  Size: 68 KiB

View file

Before

Width:  |  Height:  |  Size: 220 KiB

After

Width:  |  Height:  |  Size: 220 KiB

View file

Before

Width:  |  Height:  |  Size: 36 KiB

After

Width:  |  Height:  |  Size: 36 KiB

View file

Before

Width:  |  Height:  |  Size: 17 KiB

After

Width:  |  Height:  |  Size: 17 KiB

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