Seitenumbrüche und Weißraum FIX

This commit is contained in:
Simon Martens
2025-04-14 17:41:54 +02:00
parent 113a084f50
commit 8b5805e038
9 changed files with 317 additions and 89 deletions

View File

@@ -2,9 +2,6 @@ package functions
import (
"html/template"
"strings"
xmlparsing "github.com/Theodor-Springmann-Stiftung/lenz-web/xml"
)
func FirstLetter(s string) string {
@@ -20,41 +17,3 @@ func Safe(s string) template.HTML {
}
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

@@ -0,0 +1,155 @@
package functions
import (
"strings"
xmlparsing "github.com/Theodor-Springmann-Stiftung/lenz-web/xml"
)
type outType int
const (
NA outType = iota
Text
Element
EmptyElement
EndElement
)
type outToken struct {
Type outType
Name string
Classes []string
Id string
Value string
}
func (o *outToken) ClassesFromAttrs(attrs map[string]string) {
if len(attrs) == 0 {
return
}
for key, value := range attrs {
o.Classes = append(o.Classes, key+"-"+value)
}
}
func Default(token xmlparsing.Token) outToken {
o := outToken{}
switch token.Type {
case xmlparsing.StartElement:
o.Name = "div"
o.Type = Element
o.Classes = []string{token.Name}
o.ClassesFromAttrs(token.Attributes)
case xmlparsing.EndElement:
o.Type = EndElement
case xmlparsing.CharData:
o.Type = Text
o.Value = token.Data
}
return o
}
type LenzParseState struct {
Out []outToken
LC int
PC string
CloseElement bool
}
func (s *LenzParseState) String() string {
builder := strings.Builder{}
for _, token := range s.Out {
switch token.Type {
case Text:
builder.WriteString(token.Value)
case Element:
builder.WriteString("<")
builder.WriteString(token.Name)
if len(token.Classes) > 0 {
builder.WriteString(" class=\"")
builder.WriteString(strings.Join(token.Classes, " "))
builder.WriteString("\"")
}
if len(token.Id) > 0 {
builder.WriteString(" id=\"")
builder.WriteString(token.Id)
builder.WriteString("\"")
}
builder.WriteString(">")
case EndElement:
builder.WriteString("</div>")
case EmptyElement:
builder.WriteString("<")
builder.WriteString(token.Name)
if len(token.Classes) > 0 {
builder.WriteString(" class=\"")
builder.WriteString(strings.Join(token.Classes, " "))
builder.WriteString("\"")
}
if len(token.Id) > 0 {
builder.WriteString(" id=\"")
builder.WriteString(token.Id)
builder.WriteString("\"")
}
builder.WriteString("/>")
}
}
return builder.String()
}
func ParseGeneric(s string) string {
if len(s) == 0 {
return ""
}
ps := LenzParseState{CloseElement: true}
for elem, err := range xmlparsing.Iterate(s, ps) {
if err != nil {
return err.Error()
}
if elem.Token.Type < 3 {
if !ps.CloseElement && elem.Token.Type == xmlparsing.EndElement {
ps.CloseElement = true
continue
} else if elem.Token.Type == xmlparsing.EndElement {
ps.Out = append(ps.Out, Default(elem.Token))
continue
}
defaultToken := Default(elem.Token)
switch elem.Token.Name {
case "line":
nt := outToken{
Type: EmptyElement,
Name: "br",
}
if val := elem.Token.Attributes["type"]; val != "empty" {
ps.Out = append(ps.Out, nt)
ps.LC += 1
ps.Out = append(ps.Out, defaultToken)
} else {
nt.Classes = []string{"empty"}
ps.Out = append(ps.Out, nt)
ps.CloseElement = false
}
case "page":
ps.LC = 0
ps.PC = elem.Token.Attributes["index"]
ps.Out = append(ps.Out, defaultToken)
nt := outToken{
Type: Text,
Value: "[" + ps.PC + "]",
}
ps.Out = append(ps.Out, nt)
default:
ps.Out = append(ps.Out, defaultToken)
}
}
}
return ps.String()
}

File diff suppressed because one or more lines are too long

View File

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

View File

@@ -25,24 +25,16 @@
<div>{{- .year }}</div>
<div>({{- len $letters }})</div>
</div>
{{ range $l := $letters -}}
<a href="/brief/{{ $l.Letter }}" class="">
{{- template "_letterhead" $l -}}
</a>
{{- end -}}
{{ template "_letterlist" $letters -}}
{{- end -}}
{{- if .all -}}
{{- range $y := .years -}}
<div>
<div class="">
{{- $y -}}
{{- $letters := index $model.yearmap $y -}}
{{- len $letters }}
{{ range $l := $letters -}}
<a href="/brief/{{ $l.Letter }}" class="">
{{- template "_letterhead" $l -}}
</a>
{{- end -}}
<div>({{- len $letters }})</div>
{{ template "_letterlist" $letters -}}
</div>
{{- end -}}
{{- end -}}

View File

@@ -1,11 +1,15 @@
{{ $model := . }}
<div>{{ $model.Letter }}</div>
<div class="flex flex-row">
<div class="mr-4 text-6xl">{{ $model.Letter }}</div>
<div class="pt-0.5">
<div>{{ $model.Earliest.Text -}}</div>
{{- range $sr := $model.SendReceivedPairs -}}
<div>
<div class="flex flex-row">
<div>
{{- range $i, $p := $sr.Sent.Persons -}}
<div>
<div class="inline-block">
{{- if $i -}}
,
{{ end -}}
@@ -14,11 +18,11 @@
</div>
{{- end -}}
</div>
<div>an</div>
<div class="mx-2"><i class="ri-arrow-right-long-line"></i></div>
{{- if $sr.Received -}}
<div>
{{- range $i, $p := $sr.Received.Persons -}}
<div>
<div class="inline-block">
{{- if $i -}}
,
{{ end -}}
@@ -32,3 +36,5 @@
{{- end -}}
</div>
{{- end -}}
</div>
</div>

View File

@@ -0,0 +1,7 @@
{{- $letters := . }}
{{ range $l := $letters -}}
<a class="block mb-2" href="/brief/{{ $l.Letter }}">
{{- template "_letterhead" $l -}}
</a>
{{- end -}}

View File

@@ -74,4 +74,106 @@
nav a[aria-current="page"] {
@apply font-bold text-red-500;
}
.text {
@apply font-serif max-w-[80ch] relative;
overflow: auto;
}
.text .page,
.text .line,
.text .aq,
.text .ul,
.text .dul,
.text .it,
.text .pe,
.text .gr,
.text .hb,
.text .nr,
.text .align,
.text .insertion,
.text .del,
.text .fn,
.text .anchor {
@apply inline-block;
}
.text .aq {
@apply font-sans;
}
.text .line {
@apply w-0;
font-size: 0 !important;
}
.text .line.tab-1 {
@apply w-4;
}
.text br.index-1 {
@apply hidden;
}
.text .page {
@apply font-sans text-sm text-gray-500;
}
.text .page.index-1 {
@apply hidden;
}
.text .ul {
@apply underline;
}
.text .dul {
@apply underline decoration-double;
}
.text .it {
@apply italic;
}
.text .align.pos-right {
@apply text-right;
float: right;
}
.text .align.pos-center {
width: max-content;
position: relative;
left: 50%;
transform: translateX(-50%);
}
.text .insertion::before {
content: "⌞";
}
.text .insertion::after {
content: "⌟";
}
.text .nr::before {
content: "⸰";
}
.text .nr::after {
content: "⸰";
}
.text .pe {
@apply text-stone-600;
}
.text .del {
@apply line-through;
}
.text .del .del::before {
content: "";
@apply absolute inset-x-0 top-1/2 h-px bg-black;
top: 55%;
}
}

View File

@@ -22,18 +22,22 @@ func (d *Date) Sort() *xmlparsing.XSDDate {
if d.NotBefore.Validate() {
return &d.NotBefore
}
if d.From.Validate() {
return &d.From
}
if d.When.Validate() {
return &d.When
}
if d.To.Validate() {
return &d.To
}
if d.NotAfter.Validate() {
return &d.NotAfter
}
if d.To.Validate() {
return &d.To
}
if d.When.Validate() {
return &d.When
}
if d.From.Validate() {
return &d.From
}
return nil
}