exp akteure

This commit is contained in:
Simon Martens
2024-12-29 20:26:36 +01:00
parent 863b520d1c
commit e46d540c01
12 changed files with 151 additions and 121 deletions

View File

@@ -8,9 +8,8 @@ full_bin = "export KGPZ_WATCH=false; ./tmp/main"
cmd = "go build -tags=\"dev\" -o ./tmp/main ."
delay = 400
exclude_dir = [
"views/public",
"views/assets",
"views/node_modules",
"views/transform",
"tmp",
"vendor",
"testdata",
@@ -23,7 +22,7 @@ exclude_regex = ["_test.go"]
exclude_unchanged = false
follow_symlink = false
include_dir = []
include_ext = ["go", "tpl", "tmpl", "html", "gohtml"]
include_ext = ["go", "tpl", "tmpl", "html", "gohtml", "js", "css", "xsl"]
include_file = []
kill_delay = "0s"
log = "build-errors.log"

View File

@@ -4,6 +4,8 @@ import (
"html/template"
"io"
"io/fs"
"path/filepath"
"strings"
"sync"
)
@@ -14,6 +16,8 @@ var embed_cache sync.Map
func EmbedSafe(fs fs.FS) func(string) template.HTML {
embed_cache.Clear()
return func(path string) template.HTML {
path = strings.TrimSpace(path)
path = filepath.Clean(path)
val, err := getFileData(fs, path)
if err != nil {
return template.HTML("")
@@ -26,6 +30,8 @@ func EmbedSafe(fs fs.FS) func(string) template.HTML {
func Embed(fs fs.FS) func(string) string {
embed_cache.Clear()
return func(path string) string {
path = strings.TrimSpace(path)
path = filepath.Clean(path)
val, err := getFileData(fs, path)
if err != nil {
return ""
@@ -54,3 +60,27 @@ func getFileData(fs fs.FS, path string) ([]byte, error) {
embed_cache.Store(path, data)
return data, nil
}
func EmbedXSLT(fs fs.FS) func(string) template.HTML {
embed_cache.Clear()
return func(path string) template.HTML {
path = strings.TrimSpace(path)
path = filepath.Clean(path)
fn := filepath.Base(path)
ext := filepath.Ext(fn)
fn = fn[:len(fn)-len(ext)]
if (ext != ".xsl" && ext != ".xslt") || ext == "" || fn == "" {
return template.HTML("[ERROR: " + "file is not an XSLT file" + "]")
}
val, err := getFileData(fs, path)
if err != nil {
return template.HTML("[ERROR: " + err.Error() + "]")
}
src := "<script id=\"" + fn + "\" type=\"application/xml\">\n" + string(val) + "\n</script>"
return template.HTML(src)
}
}

View File

@@ -55,6 +55,9 @@ func (e *Engine) Funcs(app *app.KGPZ) error {
e.AddFunc("EmbedSafe", functions.EmbedSafe(views.StaticFS))
e.AddFunc("Embed", functions.Embed(views.StaticFS))
// Embedding of XSLT files
e.AddFunc("EmbedXSLT", functions.EmbedXSLT(views.StaticFS))
// App specific
e.AddFunc("GetAgent", app.Library.Agents.Item)
e.AddFunc("GetPlace", app.Library.Places.Item)

View File

@@ -1,54 +1,51 @@
const u = "[xslt-onload]", a = "xslt-template", c = "xslt-transformed", i = /* @__PURE__ */ new Map();
function p() {
let t = htmx.findAll(u);
const p = "script[xslt-onload]", a = "xslt-template", u = "xslt-transformed", c = /* @__PURE__ */ new Map();
function m() {
let t = htmx.findAll(p);
for (let e of t)
f(e);
T(e);
}
function f(t) {
if (t.getAttribute(c) === "true" || !t.hasAttribute(a))
function T(t) {
if (t.getAttribute(u) === "true" || !t.hasAttribute(a))
return;
let e = "#" + t.getAttribute(a), r = i.get(e);
if (!r) {
let o = htmx.find(e);
if (o) {
let n = o.innerHTML ? new DOMParser().parseFromString(o.innerHTML, "application/xml") : o.contentDocument;
r = new XSLTProcessor(), r.importStylesheet(n), i.set(e, r);
let e = "#" + t.getAttribute(a), o = c.get(e);
if (!o) {
let n = htmx.find(e);
if (n) {
let l = n.innerHTML ? new DOMParser().parseFromString(n.innerHTML, "application/xml") : n.contentDocument;
o = new XSLTProcessor(), o.importStylesheet(l), c.set(e, o);
} else
throw new Error("Unknown XSLT template: " + e);
}
if (r) {
let o = new DOMParser().parseFromString(t.innerHTML, "application/xml"), n = r.transformToFragment(o, document), s = new XMLSerializer().serializeToString(n);
t.innerHTML = s, t.setAttribute(c, !0), htmx.process(t);
} else
throw new Error("No Processor: " + e);
let i = new DOMParser().parseFromString(t.innerHTML, "application/xml"), s = o.transformToFragment(i, document), r = new XMLSerializer().serializeToString(s);
t.outerHTML = r;
}
function T() {
function f() {
document.querySelectorAll("template[simple]").forEach((e) => {
let r = e.getAttribute("id"), o = e.content;
let o = e.getAttribute("id"), i = e.content;
customElements.define(
r,
o,
class extends HTMLElement {
constructor() {
super(), this.appendChild(o.cloneNode(!0)), this.slots = this.querySelectorAll("slot");
super(), this.appendChild(i.cloneNode(!0)), this.slots = this.querySelectorAll("slot");
}
connectedCallback() {
let n = [];
this.slots.forEach((s) => {
let m = s.getAttribute("name"), l = this.querySelector(`[slot="${m}"]`);
l && (s.replaceWith(l.cloneNode(!0)), n.push(l));
}), n.forEach((s) => {
s.remove();
let s = [];
this.slots.forEach((r) => {
let n = r.getAttribute("name"), l = this.querySelector(`[slot="${n}"]`);
l && (r.replaceWith(l.cloneNode(!0)), s.push(l));
}), s.forEach((r) => {
r.remove();
});
}
}
);
});
}
function h() {
p(), htmx.on("htmx:afterSettle", function(t) {
i.clear(), p();
}), T();
function d() {
m(), htmx.on("htmx:load", function(t) {
m();
}), f();
}
export {
h as setup
d as setup
};

File diff suppressed because one or more lines are too long

View File

@@ -1,4 +1,5 @@
{{ if ne (len .model.Search) 1 }}
{{ $agent := index $.model.Agents .model.Search }}
{{ if not $agent }}
<div>Agent nicht gefunden: {{ .model.Search }}</div>
@@ -10,8 +11,9 @@
{{ $letter }}
</a>
</div>
<div>{{ index $agent.Names 0 }}</div>
<div>{{ template "_agent" $agent }}</div>
{{ end }}
{{ else }}
<div>
{{ range $_, $l := .model.AvailableLetters }}
@@ -23,75 +25,8 @@
{{ range $_, $id := .model.Sorted }}
{{ $a := index $.model.Agents $id }}
{{ if and $a (ne (len $a.Names) 0) }}
<div class="pb-4">
{{ index $a.Names 0 }}
<div>
{{ $gnd := GetGND $a.GND }}
{{ if (ne $gnd nil) }}
{{- if ne (len $gnd.DateOfBirth) 0 -}}
<i class="ri-asterisk text-xs relative bottom-0.5"></i>&nbsp;
{{- HRDateShort (index $gnd.DateOfBirth 0) -}}
{{- end -}}
{{- if ne (len $gnd.DateOfDeath) 0 }}
&emsp;<i class="ri-cross-fill text-xs relative bottom-0.5"></i
>&nbsp;{{ HRDateShort (index $gnd.DateOfDeath 0) }}
{{ end }}
{{- if ne (len $gnd.ProfessionOrOccupation) 0 -}}
<div>
{{- (index $gnd.ProfessionOrOccupation 0).Label -}}
{{- if gt (len $gnd.ProfessionOrOccupation) 1 -}}
,
{{ (index $gnd.ProfessionOrOccupation 1).Label -}}
{{ end -}}
{{- if gt (len $gnd.ProfessionOrOccupation) 2 -}}
,
{{ (index $gnd.ProfessionOrOccupation 2).Label -}}
{{ end -}}
</div>
{{ end }}
{{ end }}
<div class="flex gap-x-2 flex-row">
<a href="/akteure/{{ $id }}" class="!no-underline"><i class="ri-links-line"></i></a>
{{- if ne $gnd nil -}}
<a href="{{ $a.GND }}" target="_blank">GND &rarr;</a>
{{- if ne (len $gnd.Wikipedia) 0 -}}
<a href="{{ (index $gnd.Wikipedia 0).Label }}" target="_blank">WIKI &rarr;</a>
{{ end -}}
{{ end }}
</div>
</div>
{{- if ne (len $a.Works) 0 -}}
<div>
{{ range $_, $w := $a.Works }}
{{- if ne (len $w.Citation.InnerXML ) 0 -}}
<div xslt-template="citation-xslt" xslt-onload>
<xml>
{{- Safe $w.Citation.InnerXML -}}
</xml>
</div>
{{- end -}}
{{ end }}
</div>
{{ end }}
{{- if ne (len $a.Pieces) 0 -}}
<div>
{{ range $_, $p := $a.Pieces }}
{{- range $_, $i := $p.IssueRefs -}}
<div>
<a href="/{{ $i.When }}/{{ $i.Nr }}">{{ $i.Nr }}/{{ $i.When }}</a>
</div>
{{- end -}}
{{ end }}
</div>
{{ end }}
</div>
{{ end }}
{{ template "_agent" $a }}
{{ end }}
{{ end }}
<script id="citation-xslt" type="application/xml">
{{ EmbedSafe "xslt/citation.xsl" }}
</script>
{{ EmbedXSLT "xslt/transform-citation.xsl" }}

View File

@@ -0,0 +1,72 @@
{{ $a := . }}
{{ if and $a (ne (len $a.Names) 0) }}
<div class="pb-4">
{{ index $a.Names 0 }}
<div>
{{ $gnd := GetGND $a.GND }}
{{ if (ne $gnd nil) }}
{{- if ne (len $gnd.DateOfBirth) 0 -}}
<i class="ri-asterisk text-xs relative bottom-0.5"></i>&nbsp;
{{- HRDateShort (index $gnd.DateOfBirth 0) -}}
{{- end -}}
{{- if ne (len $gnd.DateOfDeath) 0 }}
&emsp;<i class="ri-cross-fill text-xs relative bottom-0.5"></i
>&nbsp;{{ HRDateShort (index $gnd.DateOfDeath 0) }}
{{ end }}
{{- if ne (len $gnd.ProfessionOrOccupation) 0 -}}
<div>
{{- (index $gnd.ProfessionOrOccupation 0).Label -}}
{{- if gt (len $gnd.ProfessionOrOccupation) 1 -}}
,
{{ (index $gnd.ProfessionOrOccupation 1).Label -}}
{{ end -}}
{{- if gt (len $gnd.ProfessionOrOccupation) 2 -}}
,
{{ (index $gnd.ProfessionOrOccupation 2).Label -}}
{{ end -}}
</div>
{{ end }}
{{ end }}
<div class="flex gap-x-2 flex-row">
<a href="/akteure/{{ $a.ID }}" class="!no-underline"><i class="ri-links-line"></i></a>
{{- if ne $gnd nil -}}
<a href="{{ $a.GND }}" target="_blank">GND &rarr;</a>
{{- if ne (len $gnd.Wikipedia) 0 -}}
<a href="{{ (index $gnd.Wikipedia 0).Label }}" target="_blank">WIKI &rarr;</a>
{{ end -}}
{{ end }}
</div>
</div>
{{- if ne (len $a.Works) 0 -}}
<div>
{{ range $_, $w := $a.Works }}
{{- if ne (len $w.Citation.InnerXML ) 0 -}}
<script type="application/xml" xslt-template="transform-citation" xslt-onload>
<xml>
{{- Safe $w.Citation.InnerXML -}}
</xml>
</script>
{{- end -}}
{{ end }}
</div>
{{ end }}
{{- if ne (len $a.Pieces) 0 -}}
<div>
{{ range $_, $p := $a.Pieces }}
{{- range $_, $i := $p.IssueRefs -}}
<div>
<a href="/{{ $i.When }}/{{ $i.Nr }}">{{ $i.Nr }}/{{ $i.When }}</a>
</div>
{{- end -}}
{{ end }}
</div>
{{ end }}
</div>
{{ end }}

View File

@@ -4,6 +4,7 @@ export default {
"./routes/**/*.{html,js,svelte,ts,tmpl,gotmpl,gohtml}",
"./layouts/**/*.{html,js,svelte,ts,tmpl,gotmpl,gohtml}",
"./transform/**/*.{html,js,svelte,ts,tmpl,gotmpl,gohtml}",
"./public/**/*.{html,js,svelte,ts,tmpl,gotmpl,gohtml,xsl}",
],
theme: {
extend: {

View File

@@ -1,6 +1,6 @@
import "./site.css";
const ATTR_XSLT_ONLOAD = "[xslt-onload]";
const ATTR_XSLT_ONLOAD = "script[xslt-onload]";
const ATTR_XSLT_TEMPLATE = "xslt-template";
const ATTR_XSLT_STATE = "xslt-transformed";
@@ -37,18 +37,10 @@ function transform_xslt(element) {
}
}
if (processor) {
let data = new DOMParser().parseFromString(element.innerHTML, "application/xml");
let frag = processor.transformToFragment(data, document);
let s = new XMLSerializer().serializeToString(frag);
element.innerHTML = s;
element.setAttribute(ATTR_XSLT_STATE, true);
// INFO: This allows to insert htmx elements in the transformed content
htmx.process(element);
} else {
throw new Error("No Processor: " + templateId);
}
let data = new DOMParser().parseFromString(element.innerHTML, "application/xml");
let frag = processor.transformToFragment(data, document);
let s = new XMLSerializer().serializeToString(frag);
element.outerHTML = s;
}
function setup_templates() {
@@ -89,8 +81,9 @@ function setup_templates() {
function setup() {
setup_xslt();
htmx.on("htmx:afterSettle", function (_) {
xslt_processors.clear();
htmx.on("htmx:load", function (_) {
// INFO: We can instead use afterSettle; and also clear the map with
// xslt_processors.clear();
setup_xslt();
});