mirror of
https://github.com/Theodor-Springmann-Stiftung/lenz-web.git
synced 2025-10-29 17:25:32 +00:00
Seitenumbrüche und Weißraum FIX
This commit is contained in:
@@ -2,9 +2,6 @@ package functions
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"html/template"
|
"html/template"
|
||||||
"strings"
|
|
||||||
|
|
||||||
xmlparsing "github.com/Theodor-Springmann-Stiftung/lenz-web/xml"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func FirstLetter(s string) string {
|
func FirstLetter(s string) string {
|
||||||
@@ -20,41 +17,3 @@ 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()
|
|
||||||
}
|
|
||||||
|
|||||||
155
helpers/functions/textparse.go
Normal file
155
helpers/functions/textparse.go
Normal 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
@@ -7,4 +7,7 @@
|
|||||||
<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) -}}
|
|
||||||
|
<div class="text">
|
||||||
|
{{- Safe (ParseGeneric .text.Content) -}}
|
||||||
|
</div>
|
||||||
|
|||||||
@@ -25,24 +25,16 @@
|
|||||||
<div>{{- .year }}</div>
|
<div>{{- .year }}</div>
|
||||||
<div>({{- len $letters }})</div>
|
<div>({{- len $letters }})</div>
|
||||||
</div>
|
</div>
|
||||||
{{ range $l := $letters -}}
|
{{ template "_letterlist" $letters -}}
|
||||||
<a href="/brief/{{ $l.Letter }}" class="">
|
|
||||||
{{- template "_letterhead" $l -}}
|
|
||||||
</a>
|
|
||||||
{{- end -}}
|
|
||||||
{{- end -}}
|
{{- end -}}
|
||||||
|
|
||||||
{{- if .all -}}
|
{{- if .all -}}
|
||||||
{{- range $y := .years -}}
|
{{- range $y := .years -}}
|
||||||
<div>
|
<div class="">
|
||||||
{{- $y -}}
|
{{- $y -}}
|
||||||
{{- $letters := index $model.yearmap $y -}}
|
{{- $letters := index $model.yearmap $y -}}
|
||||||
{{- len $letters }}
|
<div>({{- len $letters }})</div>
|
||||||
{{ range $l := $letters -}}
|
{{ template "_letterlist" $letters -}}
|
||||||
<a href="/brief/{{ $l.Letter }}" class="">
|
|
||||||
{{- template "_letterhead" $l -}}
|
|
||||||
</a>
|
|
||||||
{{- end -}}
|
|
||||||
</div>
|
</div>
|
||||||
{{- end -}}
|
{{- end -}}
|
||||||
{{- end -}}
|
{{- end -}}
|
||||||
|
|||||||
@@ -1,34 +1,40 @@
|
|||||||
{{ $model := . }}
|
{{ $model := . }}
|
||||||
<div>{{ $model.Letter }}</div>
|
|
||||||
<div>{{ $model.Earliest.Text -}}</div>
|
|
||||||
{{- range $sr := $model.SendReceivedPairs -}}
|
<div class="flex flex-row">
|
||||||
<div>
|
<div class="mr-4 text-6xl">{{ $model.Letter }}</div>
|
||||||
<div>
|
<div class="pt-0.5">
|
||||||
{{- range $i, $p := $sr.Sent.Persons -}}
|
<div>{{ $model.Earliest.Text -}}</div>
|
||||||
|
{{- range $sr := $model.SendReceivedPairs -}}
|
||||||
|
<div class="flex flex-row">
|
||||||
<div>
|
<div>
|
||||||
{{- if $i -}}
|
{{- range $i, $p := $sr.Sent.Persons -}}
|
||||||
,
|
<div class="inline-block">
|
||||||
{{ end -}}
|
{{- if $i -}}
|
||||||
{{- $person := Person $p.Reference -}}
|
,
|
||||||
{{- $person.Name -}}
|
{{ end -}}
|
||||||
|
{{- $person := Person $p.Reference -}}
|
||||||
|
{{- $person.Name -}}
|
||||||
|
</div>
|
||||||
|
{{- end -}}
|
||||||
</div>
|
</div>
|
||||||
{{- end -}}
|
<div class="mx-2"><i class="ri-arrow-right-long-line"></i></div>
|
||||||
</div>
|
{{- if $sr.Received -}}
|
||||||
<div>an</div>
|
|
||||||
{{- if $sr.Received -}}
|
|
||||||
<div>
|
|
||||||
{{- range $i, $p := $sr.Received.Persons -}}
|
|
||||||
<div>
|
<div>
|
||||||
{{- if $i -}}
|
{{- range $i, $p := $sr.Received.Persons -}}
|
||||||
,
|
<div class="inline-block">
|
||||||
{{ end -}}
|
{{- if $i -}}
|
||||||
{{- $person := Person $p.Reference -}}
|
,
|
||||||
{{- $person.Name -}}
|
{{ end -}}
|
||||||
|
{{- $person := Person $p.Reference -}}
|
||||||
|
{{- $person.Name -}}
|
||||||
|
</div>
|
||||||
|
{{- end -}}
|
||||||
</div>
|
</div>
|
||||||
|
{{- else -}}
|
||||||
|
<div>Unbekannt</div>
|
||||||
{{- end -}}
|
{{- end -}}
|
||||||
</div>
|
</div>
|
||||||
{{- else -}}
|
|
||||||
<div>Unbekannt</div>
|
|
||||||
{{- end -}}
|
{{- end -}}
|
||||||
</div>
|
</div>
|
||||||
{{- end -}}
|
</div>
|
||||||
|
|||||||
7
views/routes/components/_letterlist.gohtml
Normal file
7
views/routes/components/_letterlist.gohtml
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
{{- $letters := . }}
|
||||||
|
|
||||||
|
{{ range $l := $letters -}}
|
||||||
|
<a class="block mb-2" href="/brief/{{ $l.Letter }}">
|
||||||
|
{{- template "_letterhead" $l -}}
|
||||||
|
</a>
|
||||||
|
{{- end -}}
|
||||||
@@ -74,4 +74,106 @@
|
|||||||
nav a[aria-current="page"] {
|
nav a[aria-current="page"] {
|
||||||
@apply font-bold text-red-500;
|
@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%;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,18 +22,22 @@ func (d *Date) Sort() *xmlparsing.XSDDate {
|
|||||||
if d.NotBefore.Validate() {
|
if d.NotBefore.Validate() {
|
||||||
return &d.NotBefore
|
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() {
|
if d.NotAfter.Validate() {
|
||||||
return &d.NotAfter
|
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
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user