Basic Briefansicht + parsing

This commit is contained in:
Simon Martens
2025-04-01 18:07:57 +02:00
parent 0e2c6360bf
commit 31d40c1ce1
13 changed files with 107 additions and 55 deletions

View File

@@ -24,5 +24,5 @@ func GetLetter(c *fiber.Ctx) error {
text := lib.Letters.Item(letter) text := lib.Letters.Item(letter)
tradition := lib.Traditions.Item(letter) tradition := lib.Traditions.Item(letter)
return c.Render("/brief/", map[string]any{"meta": meta, "text": text, "tradition": tradition, "next": np.Next, "prev": np.Prev}) return c.Render("/brief/", fiber.Map{"meta": meta, "text": text, "tradition": tradition, "next": np.Next, "prev": np.Prev})
} }

View File

@@ -1,27 +1,12 @@
package controllers package controllers
import ( import (
"strconv"
"github.com/Theodor-Springmann-Stiftung/lenz-web/xmlmodels"
"github.com/gofiber/fiber/v2" "github.com/gofiber/fiber/v2"
"strconv"
) )
const DEFAULT_YEAR = 1765 const DEFAULT_YEAR = 1765
func GetIndex(c *fiber.Ctx) error { func GetIndex(c *fiber.Ctx) error {
return c.Redirect(JAHRGAENGE_URL + "/" + strconv.Itoa(DEFAULT_YEAR)) return c.Redirect(LETTERS_URL + "?year=" + strconv.Itoa(DEFAULT_YEAR))
}
func GetIndexYear(c *fiber.Ctx) error {
lib := xmlmodels.Get()
years, yearmap := lib.Years()
y := c.Params(YEAR_PARAM)
year, err := strconv.Atoi(y)
if _, ok := yearmap[year]; (err != nil || !ok) && y != "all" {
return c.SendStatus(fiber.StatusNotFound)
}
return c.Render(JAHRGAENGE_URL+"/", map[string]any{"years": years, "yearmap": yearmap, "year": year, "all": y == "all"})
} }

View File

@@ -6,30 +6,37 @@ import (
"github.com/Theodor-Springmann-Stiftung/lenz-web/server" "github.com/Theodor-Springmann-Stiftung/lenz-web/server"
"github.com/Theodor-Springmann-Stiftung/lenz-web/views" "github.com/Theodor-Springmann-Stiftung/lenz-web/views"
"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/middleware/compress" "github.com/gofiber/fiber/v2/middleware/compress"
) )
const INDEX_URL = "/" const (
const ASSETS_URL = "/assets" INDEX_URL = "/"
const DATENSCHUTZ_URL = "/datenschutz" ASSETS_URL = "/assets"
const JAHRGAENGE_URL = "/jahrgang" DATENSCHUTZ_URL = "/datenschutz"
const ZITATION_URL = "/ausgabe/zitation" LETTERS_URL = "/briefe"
const EDITION_URL = "/ausgabe/edition" ZITATION_URL = "/ausgabe/zitation"
const KONTAKT_URL = "/kontakt" EDITION_URL = "/ausgabe/edition"
KONTAKT_URL = "/kontakt"
var INDEX_YEAR_URL = JAHRGAENGE_URL + "/:" + YEAR_PARAM LETTER_URL = "/brief/:" + LETTER_PARAM
var LETTER_URL = "/brief/:" + LETTER_PARAM YEAR_PARAM = "year"
LETTER_PARAM = "letter"
const YEAR_PARAM = "year" )
const LETTER_PARAM = "letter"
func Register(server server.Server, cfg config.Config) { func Register(server server.Server, cfg config.Config) {
server.Server.Use(ASSETS_URL, compress.New(compress.Config{ server.Server.Use(ASSETS_URL, compress.New(compress.Config{
Level: compress.LevelBestSpeed, Level: compress.LevelBestSpeed,
})) }))
server.Server.Use(ASSETS_URL, middleware.StaticHandler(&views.StaticFS)) server.Server.Use(ASSETS_URL, middleware.StaticHandler(&views.StaticFS))
server.Server.Use(func(ctx *fiber.Ctx) error {
ctx.Locals("cfg", cfg)
ctx.Locals("path", ctx.Path())
return ctx.Next()
})
server.Server.Get(INDEX_URL, GetIndex) server.Server.Get(INDEX_URL, GetIndex)
server.Server.Get(INDEX_YEAR_URL, GetIndexYear) server.Server.Get(LETTERS_URL, GetLetters)
server.Server.Get(LETTER_URL, GetLetter) server.Server.Get(LETTER_URL, GetLetter)
server.Server.Get(DATENSCHUTZ_URL, Static(DATENSCHUTZ_URL+"/")) server.Server.Get(DATENSCHUTZ_URL, Static(DATENSCHUTZ_URL+"/"))

View File

@@ -11,6 +11,6 @@ func Static(url string) fiber.Handler {
url += "/" url += "/"
} }
return func(c *fiber.Ctx) error { return func(c *fiber.Ctx) error {
return c.Render(url, map[string]any{}) return c.Render(url, fiber.Map{"Was": "Static"})
} }
} }

23
controllers/uebersicht.go Normal file
View File

@@ -0,0 +1,23 @@
package controllers
import (
"strconv"
"github.com/Theodor-Springmann-Stiftung/lenz-web/xmlmodels"
"github.com/gofiber/fiber/v2"
)
func GetLetters(c *fiber.Ctx) error {
lib := xmlmodels.Get()
years, yearmap := lib.Years()
y := c.Query(YEAR_PARAM, strconv.Itoa(DEFAULT_YEAR))
// TODO: does not work ATM
c.Locals("path", c.Path())
year, err := strconv.Atoi(y)
if _, ok := yearmap[year]; (err != nil || !ok) && y != "all" {
return c.SendStatus(fiber.StatusNotFound)
}
return c.Render(LETTERS_URL+"/", fiber.Map{"years": years, "yearmap": yearmap, "year": year, "all": y == "all"})
}

View File

@@ -1,6 +1,11 @@
package functions package functions
import "html/template" import (
"html/template"
"strings"
xmlparsing "github.com/Theodor-Springmann-Stiftung/lenz-web/xml"
)
func FirstLetter(s string) string { func FirstLetter(s string) string {
if len(s) == 0 { if len(s) == 0 {
@@ -15,3 +20,41 @@ func Safe(s string) template.HTML {
} }
return template.HTML(s) return template.HTML(s)
} }
type LenzParseState struct{}
func ParseGeneric(s string) string {
if len(s) == 0 {
return ""
}
builder := strings.Builder{}
for elem, err := range xmlparsing.Iterate(s, LenzParseState{}) {
if err != nil {
return err.Error()
}
switch elem.Token.Type {
case xmlparsing.StartElement:
builder.WriteString("<div class=\"")
builder.WriteString(elem.Token.Name)
for key, value := range elem.Token.Attributes {
builder.WriteString(" ")
builder.WriteString(key)
builder.WriteString("-")
builder.WriteString(value)
}
builder.WriteString("\">")
}
if elem.Token.Type == xmlparsing.CharData {
builder.WriteString(elem.Token.Data)
}
if elem.Token.Type == xmlparsing.EndElement {
builder.WriteString("</div>")
}
}
return builder.String()
}

View File

@@ -9,6 +9,7 @@ import (
"github.com/Theodor-Springmann-Stiftung/lenz-web/config" "github.com/Theodor-Springmann-Stiftung/lenz-web/config"
"github.com/Theodor-Springmann-Stiftung/lenz-web/controllers" "github.com/Theodor-Springmann-Stiftung/lenz-web/controllers"
gitprovider "github.com/Theodor-Springmann-Stiftung/lenz-web/git" gitprovider "github.com/Theodor-Springmann-Stiftung/lenz-web/git"
"github.com/Theodor-Springmann-Stiftung/lenz-web/helpers/functions"
"github.com/Theodor-Springmann-Stiftung/lenz-web/server" "github.com/Theodor-Springmann-Stiftung/lenz-web/server"
"github.com/Theodor-Springmann-Stiftung/lenz-web/templating" "github.com/Theodor-Springmann-Stiftung/lenz-web/templating"
"github.com/Theodor-Springmann-Stiftung/lenz-web/views" "github.com/Theodor-Springmann-Stiftung/lenz-web/views"
@@ -52,7 +53,7 @@ func main() {
engine := templating.New(&views.LayoutFS, &views.RoutesFS) engine := templating.New(&views.LayoutFS, &views.RoutesFS)
engine.AddFuncs(lib.FuncMap()) engine.AddFuncs(lib.FuncMap())
engine.AddFunc("ParseGeneric", functions.ParseGeneric)
storage := memory.New(memory.Config{ storage := memory.New(memory.Config{
GCInterval: 24 * time.Hour, GCInterval: 24 * time.Hour,
}) })

View File

@@ -47,14 +47,6 @@ func New(engine *templating.Engine, storage fiber.Storage, debug bool) Server {
PassLocalsToViews: true, PassLocalsToViews: true,
}) })
if debug {
server.Use(logger.New())
}
if !debug {
server.Use(recover.New())
}
if debug { if debug {
server.Use(cache.New(cache.Config{ server.Use(cache.New(cache.Config{
Next: CacheFunc, Next: CacheFunc,
@@ -62,13 +54,17 @@ func New(engine *templating.Engine, storage fiber.Storage, debug bool) Server {
CacheControl: false, CacheControl: false,
Storage: storage, Storage: storage,
})) }))
} else { server.Use(logger.New())
}
if !debug {
server.Use(cache.New(cache.Config{ server.Use(cache.New(cache.Config{
Next: CacheFunc, Next: CacheFunc,
Expiration: CACHE_TIME, Expiration: CACHE_TIME,
CacheControl: true, CacheControl: true,
Storage: storage, Storage: storage,
})) }))
server.Use(recover.New())
} }
return Server{ return Server{

View File

@@ -11,6 +11,7 @@ import (
"sync" "sync"
"github.com/Theodor-Springmann-Stiftung/lenz-web/helpers/functions" "github.com/Theodor-Springmann-Stiftung/lenz-web/helpers/functions"
"github.com/gofiber/fiber/v2"
"golang.org/x/net/websocket" "golang.org/x/net/websocket"
) )
@@ -188,18 +189,14 @@ func (e *Engine) AddFuncs(funcs template.FuncMap) {
} }
func (e *Engine) Render(out io.Writer, path string, data any, layout ...string) error { func (e *Engine) Render(out io.Writer, path string, data any, layout ...string) error {
slog.Debug("Rendering template", "path", path, "layout", layout, "data", data) slog.Debug("Rendering", "path", path, "layout", layout, "data", data)
e.mu.RLock() e.mu.RLock()
ld := data.(map[string]any) ld := data.(fiber.Map)
if e.GlobalData != nil { if e.GlobalData != nil {
maps.Copy(ld, e.GlobalData) maps.Copy(ld, e.GlobalData)
} }
e.mu.RUnlock() e.mu.RUnlock()
if e.debug {
slog.Debug("Rendering template", "path", path, "layout", layout, "data", ld)
}
e.regmu.RLock() e.regmu.RLock()
defer e.regmu.RUnlock() defer e.regmu.RUnlock()
var l *template.Template var l *template.Template

View File

@@ -1,10 +1,8 @@
{{ $model := . }} {{ $model := . }}
<nav class="flex flex-row gap-x-1 justify-between"> <nav class="flex flex-row gap-x-1 justify-between">
<div> <div>
<a class="inline-block px-0.5" href="/"> J.M.R. Lenz: Kritische Briefausgabe </a> <a class="inline-block px-0.5" href="/"> J.M.R. Lenz: Kritische Briefausgabe </a>
</div> </div>
<a href="/jahrgang/1765" class="inline-block px-0.5">Jahrgänge </a> <a href="/briefe?year=1765" class="inline-block px-0.5">Jahrgänge </a>
{{ .path }}
</nav> </nav>

View File

@@ -6,3 +6,5 @@
{{ if .next }} {{ if .next }}
<a href="/brief/{{ .next.Letter }}" class="stdlink">Nächster</a> <a href="/brief/{{ .next.Letter }}" class="stdlink">Nächster</a>
{{ end }} {{ end }}
{{- Safe (ParseGeneric .text.Content) -}}

View File

@@ -5,14 +5,14 @@
{{- range $y := .years -}} {{- range $y := .years -}}
<a <a
class="inline-block stdlink px-0.5" class="inline-block stdlink px-0.5"
href="/jahrgang/{{ $y }}" href="/briefe?year={{ $y }}"
{{ if eq $model.year $y -}}aria-current="page"{{- end }} {{ if eq $model.year $y -}}aria-current="page"{{- end }}
>{{ $y }}</a >{{ $y }}</a
> >
{{- end -}} {{- end -}}
<a <a
class="inline-block stdlink px-0.5" class="inline-block stdlink px-0.5"
href="/jahrgang/all" href="/briefe?year=all"
{{ if .all -}}aria-current="page"{{- end }} {{ if .all -}}aria-current="page"{{- end }}
>Alle</a >Alle</a
> >