mirror of
https://github.com/Theodor-Springmann-Stiftung/lenz-web.git
synced 2025-10-29 09:15:33 +00:00
Sidenote-Start
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
package functions
|
package functions
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"math/rand"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
@@ -8,13 +9,18 @@ import (
|
|||||||
"github.com/Theodor-Springmann-Stiftung/lenz-web/xmlmodels"
|
"github.com/Theodor-Springmann-Stiftung/lenz-web/xmlmodels"
|
||||||
)
|
)
|
||||||
|
|
||||||
type outType int
|
const charset = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
|
||||||
|
|
||||||
var endDivToken = outToken{
|
func RandString(length int) string {
|
||||||
Type: EndElement,
|
b := make([]byte, length)
|
||||||
Name: "div",
|
for i := range b {
|
||||||
|
b[i] = charset[rand.Intn(len(charset))]
|
||||||
|
}
|
||||||
|
return string(b)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type outType int
|
||||||
|
|
||||||
const (
|
const (
|
||||||
NA outType = iota
|
NA outType = iota
|
||||||
Text
|
Text
|
||||||
@@ -24,11 +30,58 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type outToken struct {
|
type outToken struct {
|
||||||
Type outType
|
Type outType
|
||||||
Name string
|
Name string
|
||||||
Classes []string
|
Classes []string
|
||||||
Id string
|
Id string
|
||||||
Value string
|
Value string
|
||||||
|
Attributes map[string]string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (o outToken) String() string {
|
||||||
|
switch o.Type {
|
||||||
|
case Text:
|
||||||
|
return o.Value
|
||||||
|
|
||||||
|
case Element:
|
||||||
|
builder := strings.Builder{}
|
||||||
|
builder.WriteString("<")
|
||||||
|
builder.WriteString(o.Name)
|
||||||
|
if len(o.Classes) > 0 {
|
||||||
|
builder.WriteString(" class=\"")
|
||||||
|
builder.WriteString(strings.Join(o.Classes, " "))
|
||||||
|
builder.WriteString("\"")
|
||||||
|
}
|
||||||
|
if len(o.Id) > 0 {
|
||||||
|
builder.WriteString(" id=\"")
|
||||||
|
builder.WriteString(o.Id)
|
||||||
|
builder.WriteString("\"")
|
||||||
|
}
|
||||||
|
builder.WriteString(">")
|
||||||
|
return builder.String()
|
||||||
|
|
||||||
|
case EndElement:
|
||||||
|
return "</" + o.Name + ">"
|
||||||
|
|
||||||
|
case EmptyElement:
|
||||||
|
builder := strings.Builder{}
|
||||||
|
builder.WriteString("<")
|
||||||
|
builder.WriteString(o.Name)
|
||||||
|
if len(o.Classes) > 0 {
|
||||||
|
builder.WriteString(" class=\"")
|
||||||
|
builder.WriteString(strings.Join(o.Classes, " "))
|
||||||
|
builder.WriteString("\"")
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(o.Id) > 0 {
|
||||||
|
builder.WriteString(" id=\"")
|
||||||
|
builder.WriteString(o.Id)
|
||||||
|
builder.WriteString("\"")
|
||||||
|
}
|
||||||
|
builder.WriteString("/>")
|
||||||
|
}
|
||||||
|
|
||||||
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func (o *outToken) ClassesFromAttrs(attrs map[string]string) {
|
func (o *outToken) ClassesFromAttrs(attrs map[string]string) {
|
||||||
@@ -67,45 +120,69 @@ type LenzParseState struct {
|
|||||||
func (s *LenzParseState) String() string {
|
func (s *LenzParseState) String() string {
|
||||||
builder := strings.Builder{}
|
builder := strings.Builder{}
|
||||||
for _, token := range s.Out {
|
for _, token := range s.Out {
|
||||||
switch token.Type {
|
builder.WriteString(token.String())
|
||||||
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()
|
return builder.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *LenzParseState) AppendDefaultElement(token xmlparsing.Token, ids ...string) {
|
||||||
|
t := Default(token)
|
||||||
|
if len(ids) > 0 {
|
||||||
|
t.Id = ids[0]
|
||||||
|
}
|
||||||
|
|
||||||
|
s.Out = append(s.Out, t)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *LenzParseState) AppendEndElement() {
|
||||||
|
for i := len(s.Out) - 1; i >= 0; i-- {
|
||||||
|
if s.Out[i].Type == Element {
|
||||||
|
s.Out = append(s.Out, outToken{
|
||||||
|
Name: s.Out[i].Name,
|
||||||
|
Type: EndElement,
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *LenzParseState) AppendDivElement(id string, classes ...string) {
|
||||||
|
s.Out = append(s.Out, outToken{
|
||||||
|
Name: "div",
|
||||||
|
Id: id,
|
||||||
|
Classes: classes,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *LenzParseState) AppendEmptyElement(name string, id string, classes ...string) {
|
||||||
|
s.Out = append(s.Out, outToken{
|
||||||
|
Name: name,
|
||||||
|
Id: id,
|
||||||
|
Classes: classes,
|
||||||
|
Type: EmptyElement,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *LenzParseState) AppendLink(href string, classes ...string) {
|
||||||
|
s.Out = append(s.Out, outToken{
|
||||||
|
Name: "a",
|
||||||
|
Attributes: map[string]string{"href": href},
|
||||||
|
Classes: classes,
|
||||||
|
Type: Element,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *LenzParseState) AppendText(text string) {
|
||||||
|
s.Out = append(s.Out, outToken{
|
||||||
|
Type: Text,
|
||||||
|
Value: text,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *LenzParseState) Append(token outToken) {
|
||||||
|
s.Out = append(s.Out, token)
|
||||||
|
}
|
||||||
|
|
||||||
func Parse(lib *xmlmodels.Library) func(s string) string {
|
func Parse(lib *xmlmodels.Library) func(s string) string {
|
||||||
return func(s string) string {
|
return func(s string) string {
|
||||||
if len(s) == 0 {
|
if len(s) == 0 {
|
||||||
@@ -120,124 +197,87 @@ func Parse(lib *xmlmodels.Library) func(s string) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if elem.Token.Type < 3 {
|
if elem.Token.Type < 3 {
|
||||||
if !ps.CloseElement && elem.Token.Type == xmlparsing.EndElement {
|
if elem.Token.Type == xmlparsing.EndElement {
|
||||||
ps.CloseElement = true
|
if ps.CloseElement {
|
||||||
continue
|
ps.AppendEndElement()
|
||||||
} else if elem.Token.Type == xmlparsing.EndElement {
|
} else {
|
||||||
ps.Out = append(ps.Out, Default(elem.Token))
|
ps.CloseElement = true
|
||||||
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
defaultToken := Default(elem.Token)
|
|
||||||
switch elem.Token.Name {
|
switch elem.Token.Name {
|
||||||
|
|
||||||
case "sidenote":
|
case "sidenote":
|
||||||
nt := outToken{
|
id := RandString(8)
|
||||||
Type: Element,
|
if elem.Token.Attributes["annotation"] != "" ||
|
||||||
Name: "div",
|
elem.Token.Attributes["page"] != "" ||
|
||||||
Classes: []string{"sidenote"},
|
elem.Token.Attributes["pos"] != "" {
|
||||||
|
ps.AppendLink("#"+id, "nanchor-sidenote")
|
||||||
|
ps.AppendEndElement()
|
||||||
|
ps.AppendDivElement(id, "note-sidenote-meta")
|
||||||
|
if elem.Token.Attributes["annotation"] != "" {
|
||||||
|
ps.AppendDivElement("", "sidenote-note")
|
||||||
|
ps.AppendText(elem.Token.Attributes["annotation"])
|
||||||
|
ps.AppendEndElement()
|
||||||
|
}
|
||||||
|
if elem.Token.Attributes["page"] != "" {
|
||||||
|
ps.AppendDivElement("", "sidenote-page")
|
||||||
|
ps.AppendText(elem.Token.Attributes["page"])
|
||||||
|
ps.AppendEndElement()
|
||||||
|
}
|
||||||
|
if elem.Token.Attributes["pos"] != "" {
|
||||||
|
ps.AppendDivElement("", "sidenote-pos")
|
||||||
|
ps.AppendText(elem.Token.Attributes["pos"])
|
||||||
|
ps.AppendEndElement()
|
||||||
|
}
|
||||||
|
ps.AppendEndElement() // sidenote-meta
|
||||||
}
|
}
|
||||||
ps.Out = append(ps.Out, nt)
|
ps.AppendDefaultElement(elem.Token, id)
|
||||||
metatoken := outToken{
|
|
||||||
Type: Element,
|
|
||||||
Name: "div",
|
|
||||||
Classes: []string{"sidenote-meta"},
|
|
||||||
}
|
|
||||||
ps.Out = append(ps.Out, metatoken)
|
|
||||||
if elem.Token.Attributes["annotation"] != "" {
|
|
||||||
note := outToken{
|
|
||||||
Type: Element,
|
|
||||||
Name: "div",
|
|
||||||
Classes: []string{"sidenote-note"},
|
|
||||||
}
|
|
||||||
notecontent := outToken{
|
|
||||||
Type: Text,
|
|
||||||
Value: elem.Token.Attributes["annotation"],
|
|
||||||
}
|
|
||||||
ps.Out = append(ps.Out, note, notecontent, endDivToken)
|
|
||||||
}
|
|
||||||
if elem.Token.Attributes["page"] != "" {
|
|
||||||
note := outToken{
|
|
||||||
Type: Element,
|
|
||||||
Name: "div",
|
|
||||||
Classes: []string{"sidenote-page"},
|
|
||||||
}
|
|
||||||
notecontent := outToken{
|
|
||||||
Type: Text,
|
|
||||||
Value: elem.Token.Attributes["page"],
|
|
||||||
}
|
|
||||||
ps.Out = append(ps.Out, note, notecontent, endDivToken)
|
|
||||||
}
|
|
||||||
if elem.Token.Attributes["pos"] != "" {
|
|
||||||
note := outToken{
|
|
||||||
Type: Element,
|
|
||||||
Name: "div",
|
|
||||||
Classes: []string{"sidenote-pos"},
|
|
||||||
}
|
|
||||||
notecontent := outToken{
|
|
||||||
Type: Text,
|
|
||||||
Value: elem.Token.Attributes["pos"],
|
|
||||||
}
|
|
||||||
ps.Out = append(ps.Out, note, notecontent, endDivToken)
|
|
||||||
}
|
|
||||||
ps.Out = append(ps.Out, endDivToken)
|
|
||||||
case "note":
|
case "note":
|
||||||
nt := outToken{
|
id := RandString(8)
|
||||||
Type: Element,
|
ps.AppendLink("#"+id, "nanchor-note")
|
||||||
Name: "div",
|
ps.AppendEndElement()
|
||||||
Classes: []string{"note-anchor"},
|
ps.AppendDivElement(id, "note", "note-note")
|
||||||
}
|
|
||||||
ps.Out = append(ps.Out, nt, endDivToken)
|
|
||||||
case "hand":
|
case "hand":
|
||||||
nt := outToken{
|
|
||||||
Type: Element,
|
|
||||||
Name: "div",
|
|
||||||
Classes: []string{"hand"},
|
|
||||||
}
|
|
||||||
ps.Out = append(ps.Out, nt)
|
|
||||||
id := elem.Token.Attributes["ref"]
|
id := elem.Token.Attributes["ref"]
|
||||||
idno, err := strconv.Atoi(id)
|
idno, err := strconv.Atoi(id)
|
||||||
var person *xmlmodels.PersonDef
|
var person *xmlmodels.PersonDef
|
||||||
if err == nil {
|
if err == nil {
|
||||||
person = lib.Persons.Item(idno)
|
person = lib.Persons.Item(idno)
|
||||||
}
|
}
|
||||||
handtok := outToken{
|
ps.AppendLink("#"+id, "nanchor-hand")
|
||||||
Type: Element,
|
ps.AppendEndElement()
|
||||||
Name: "div",
|
ps.AppendDivElement(id, "note-hand")
|
||||||
Classes: []string{"hand-person"},
|
hand := "N/A"
|
||||||
}
|
|
||||||
defhand := outToken{
|
|
||||||
Type: Text,
|
|
||||||
Value: "N/A",
|
|
||||||
}
|
|
||||||
if person != nil {
|
if person != nil {
|
||||||
defhand.Value = person.Name
|
hand = person.Name
|
||||||
}
|
}
|
||||||
ps.Out = append(ps.Out, handtok, defhand, endDivToken)
|
ps.AppendText(hand)
|
||||||
|
ps.AppendEndElement()
|
||||||
|
ps.AppendDefaultElement(elem.Token)
|
||||||
|
|
||||||
case "line":
|
case "line":
|
||||||
nt := outToken{
|
|
||||||
Type: EmptyElement,
|
|
||||||
Name: "br",
|
|
||||||
}
|
|
||||||
if val := elem.Token.Attributes["type"]; val != "empty" {
|
if val := elem.Token.Attributes["type"]; val != "empty" {
|
||||||
ps.Out = append(ps.Out, nt)
|
|
||||||
ps.LC += 1
|
ps.LC += 1
|
||||||
ps.Out = append(ps.Out, defaultToken)
|
ps.AppendEmptyElement("br", ps.PC+"-"+strconv.Itoa(ps.LC))
|
||||||
|
ps.AppendDefaultElement(elem.Token) // This is for indents, must be closed
|
||||||
} else {
|
} else {
|
||||||
nt.Classes = []string{"empty"}
|
ps.AppendEmptyElement("br", "", "empty")
|
||||||
ps.Out = append(ps.Out, nt)
|
ps.CloseElement = false // Here Indents make no sense, so we dont open an element
|
||||||
ps.CloseElement = false
|
|
||||||
}
|
}
|
||||||
|
|
||||||
case "page":
|
case "page":
|
||||||
ps.LC = 0
|
|
||||||
ps.PC = elem.Token.Attributes["index"]
|
ps.PC = elem.Token.Attributes["index"]
|
||||||
ps.Out = append(ps.Out, defaultToken)
|
ps.AppendLink("#"+ps.PC, "eanchor-page")
|
||||||
nt := outToken{
|
ps.AppendEndElement()
|
||||||
Type: Text,
|
ps.AppendDivElement(ps.PC, "page")
|
||||||
Value: "[" + ps.PC + "]",
|
ps.AppendText(ps.PC)
|
||||||
}
|
|
||||||
ps.Out = append(ps.Out, nt)
|
|
||||||
default:
|
default:
|
||||||
ps.Out = append(ps.Out, defaultToken)
|
ps.AppendDefaultElement(elem.Token)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
<div class="tradition-header font-bold">
|
<div class="tradition-header font-bold">
|
||||||
{{- (App $trad.Reference).Name -}}
|
{{- (App $trad.Reference).Name -}}
|
||||||
</div>
|
</div>
|
||||||
<div class="tradition-text">
|
<div class="tradition-text text hyphens-auto font-sans">
|
||||||
{{- Safe (ParseGeneric $trad.Content) -}}
|
{{- Safe (ParseGeneric $trad.Content) -}}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
Reference in New Issue
Block a user