A lot sof small qualtiy of life upgrades

This commit is contained in:
Simon Martens
2025-09-16 17:02:58 +02:00
parent 3ebfcd410f
commit ca51a6317b
17 changed files with 2109 additions and 1407 deletions

View File

@@ -13,10 +13,10 @@ The application follows a modular Go architecture:
- **Main Application**: `kgpz_web.go` - Entry point and application lifecycle management
- **App Core**: `app/kgpz.go` - Core business logic and data processing
- **Controllers**: Route handlers for different content types (issues, agents, places, categories, search)
- **View Models**: Data structures for template rendering (`viewmodels/`)
- **View Models**: Data structures for template rendering with pre-processed business logic (`viewmodels/`)
- **XML Models**: Data structures for parsing source XML files (`xmlmodels/`)
- **Providers**: External service integrations (Git, GND, XML parsing, search)
- **Templating**: Custom template engine with Go template integration
- **Templating**: Custom template engine with Go template integration and helper functions
- **Views**: Frontend assets and templates in `views/` directory
### Key Components
@@ -24,7 +24,7 @@ The application follows a modular Go architecture:
1. **Data Sources**: XML files from Git repository containing historical newspaper metadata
2. **Search**: Full-text search powered by Bleve search engine
3. **External Integrations**: GND (Gemeinsame Normdatei) for person metadata, Geonames for place data
4. **Template System**: Custom engine supporting layouts and partials with embedded filesystem
4. **Template System**: Custom engine supporting layouts and partials with embedded filesystem and helper functions
## Development Commands
@@ -154,10 +154,12 @@ Each route has dedicated `head.gohtml` and `body.gohtml` files following Go temp
- HTMX-powered interactions for dynamic content loading
**Template Features**:
- Go template syntax with custom functions from `app/kgpz.go`
- Go template syntax with custom functions from `templating/engine.go`
- Block template inheritance system
- HTMX integration for progressive enhancement
- Conditional development/production asset loading
- Template helper functions for UI components (PageIcon, BeilagePageIcon)
- Pre-processed view models to minimize template logic
### Frontend Assets
@@ -187,10 +189,43 @@ The root template conditionally loads assets based on environment:
- Module imports: ES6 modules with `setup()` function from compiled scripts
- Deferred loading: HTMX and Alpine.js loaded with `defer` attribute
## Template Architecture & Best Practices
### View Model Philosophy
The application follows a **logic-in-Go, presentation-in-templates** approach:
- **View Models** (`viewmodels/issue_view.go`): Pre-process all business logic, calculations, and data transformations
- **Templates**: Focus purely on presentation using pre-calculated data
- **Helper Functions** (`templating/engine.go`): Reusable UI components and formatting
### Key View Model Features
- **Pre-calculated metadata**: Page icons, grid layouts, visibility flags
- **Grouped data structures**: Complex relationships resolved in Go
- **Template helpers**: `PageIcon()`, `BeilagePageIcon()` for consistent UI components
### Template Organization
**Ausgabe (Issue) Templates**:
- `body.gohtml`: Main layout structure with conditional rendering
- `components/_inhaltsverzeichnis.gohtml`: Table of contents with pre-processed page data
- `components/_newspaper_layout.gohtml`: Newspaper page grid with absolute positioning
- `components/_bilder.gohtml`: Simple image gallery fallback
- Interactive highlighting system with intersection observer and scroll detection
### JavaScript Integration
- **Progressive Enhancement**: HTMX + Alpine.js for interactivity
- **Real-time Highlighting**: Intersection Observer API with scroll fallback
- **Page Navigation**: Smooth scrolling with visibility detection
- **Responsive Design**: Mobile-optimized with proper touch interactions
## Development Workflow
1. Backend changes: Modify Go files, restart server
2. Template changes: Edit templates in `views/`, automatic reload if watching enabled
3. CSS changes: Run `npm run css` or `npm run tailwind` in views directory
4. JavaScript changes: Edit `transform/main.js`, run `npm run build`
5. Full rebuild: `go build` for backend, `npm run build` for frontend assets
5. Full rebuild: `go build` for backend, `npm run build` for frontend assets
### Adding New Template Logic
1. **First**: Add business logic to view models in Go
2. **Second**: Create reusable template helper functions if needed
3. **Last**: Use pre-processed data in templates for presentation only

View File

@@ -10,8 +10,10 @@ import (
// An implementation of the xsd 1.1 datatypes:
// date, gDay, gMonth, gMonthDay, gYear, gYearMonth.
type XSDDatetype int
type Seperator byte
type (
XSDDatetype int
Seperator byte
)
const (
DEFAULT_YEAR = 0
@@ -39,6 +41,11 @@ const (
GYearMonth
)
var (
MonthNameShort = []string{"Jan", "Feb", "März", "Apr", "Mai", "Jun", "Jul", "Aug", "Sept", "Oct", "Nov", "Dec"}
MonthName = []string{"Januar", "Februar", "März", "April", "Mai", "Juni", "Juli", "August", "September", "Oktober", "November", "Dezember"}
)
type XSDDate struct {
base string
@@ -123,6 +130,20 @@ func (d XSDDate) String() string {
return s
}
func (d *XSDDate) MonthName() string {
if d.Month == 0 {
return ""
}
return MonthName[d.Month-1]
}
func (d *XSDDate) MonthNameShort() string {
if d.Month == 0 {
return ""
}
return MonthNameShort[d.Month-1]
}
func (d *XSDDate) UnmarshalText(text []byte) error {
return d.Parse(string(text))
}

View File

@@ -41,6 +41,22 @@ func NewEngine(layouts, templates *fs.FS) *Engine {
return &e
}
// PageIcon renders the appropriate icon HTML for a page based on its icon type
func PageIcon(iconType string) template.HTML {
switch iconType {
case "first":
return template.HTML(`<i class="ri-file-text-line text-black text-sm"></i>`)
case "last":
return template.HTML(`<i class="ri-file-text-line text-black text-sm" style="transform: scaleX(-1); display: inline-block;"></i>`)
case "even":
return template.HTML(`<i class="ri-file-text-line text-black text-sm" style="margin-left: 2px; transform: scaleX(-1); display: inline-block;"></i><i class="ri-file-text-line text-slate-400 text-sm"></i>`)
case "odd":
return template.HTML(`<i class="ri-file-text-line text-slate-400 text-sm" style="margin-left: 2px; transform: scaleX(-1); display: inline-block;"></i><i class="ri-file-text-line text-black text-sm" ></i>`)
default:
return template.HTML(`<i class="ri-file-text-line text-black text-sm"></i>`)
}
}
func (e *Engine) funcs() error {
e.mu.Lock()
e.mu.Unlock()
@@ -55,6 +71,16 @@ func (e *Engine) funcs() error {
e.AddFunc("sub", func(a, b int) int { return a - b })
e.AddFunc("add", func(a, b int) int { return a + b })
e.AddFunc("mod", func(a, b int) int { return a % b })
e.AddFunc("seq", func(start, end int) []int {
if start > end {
return []int{}
}
result := make([]int, end-start+1)
for i := range result {
result[i] = start + i
}
return result
})
// Strings
e.AddFunc("FirstLetter", functions.FirstLetter)
@@ -68,6 +94,9 @@ func (e *Engine) funcs() error {
e.AddFunc("Embed", embedder.Embed())
e.AddFunc("EmbedXSLT", embedder.EmbedXSLT())
// Page icons for ausgabe templates
e.AddFunc("PageIcon", PageIcon)
return nil
}

View File

@@ -26,23 +26,28 @@ type PiecesByPage struct {
Pages []int
}
// GroupedPieceByIssue represents a piece that may span multiple consecutive pages
type GroupedPieceByIssue struct {
// IndividualPieceByIssue represents a piece with metadata for individual page display
type IndividualPieceByIssue struct {
PieceByIssue
StartPage int
EndPage int // Same as StartPage if not grouped
IssueRefs []xmlmodels.IssueRef // All issues this piece appears in
PageIcon string // Icon type: "first", "last", "even", "odd"
}
// GroupedPiecesByPage holds pieces grouped by consecutive pages when identical
type GroupedPiecesByPage struct {
Items map[int][]GroupedPieceByIssue
// IndividualPiecesByPage holds pieces as individual page entries
type IndividualPiecesByPage struct {
Items map[int][]IndividualPieceByIssue
Pages []int
}
type IssuePage struct {
PageNumber int
ImagePath string
Available bool
PageNumber int
ImagePath string
Available bool
GridColumn int // 1 or 2 for left/right positioning
GridRow int // Row number in grid
HasHeader bool // Whether this page has a double-spread header
HeaderText string // Text for double-spread header
PageIcon string // Icon type: "first", "last", "even", "odd"
}
type IssueImages struct {
@@ -72,11 +77,12 @@ var imageRegistry *ImageRegistry
// TODO: Next & Prev
type IssueVM struct {
xmlmodels.Issue
Next *xmlmodels.Issue
Prev *xmlmodels.Issue
Pieces GroupedPiecesByPage
AdditionalPieces GroupedPiecesByPage
Images IssueImages
Next *xmlmodels.Issue
Prev *xmlmodels.Issue
Pieces IndividualPiecesByPage
AdditionalPieces IndividualPiecesByPage
Images IssueImages
HasBeilageButton bool // Whether to show beilage navigation button
}
func NewSingleIssueView(y, no int, lib *xmlmodels.Library) (*IssueVM, error) {
@@ -122,14 +128,15 @@ func NewSingleIssueView(y, no int, lib *xmlmodels.Library) (*IssueVM, error) {
slices.Sort(ppa.Pages)
// Group consecutive continuation pieces
sivm.Pieces = GroupConsecutiveContinuations(ppi)
sivm.AdditionalPieces = GroupConsecutiveContinuations(ppa)
sivm.Pieces = CreateIndividualPagesWithMetadata(ppi, lib)
sivm.AdditionalPieces = CreateIndividualPagesWithMetadata(ppa, lib)
images, err := LoadIssueImages(*issue)
if err != nil {
return nil, err
}
sivm.Images = images
sivm.HasBeilageButton = len(sivm.AdditionalPieces.Pages) > 0
return &sivm, nil
}
@@ -211,105 +218,157 @@ func pagesHaveIdenticalContent(items1, items2 []PieceByIssue) bool {
return true
}
// pageContainsOnlyContinuations checks if a page contains only continuation pieces
func pageContainsOnlyContinuations(pageItems []PieceByIssue) bool {
if len(pageItems) == 0 {
return false
}
for _, piece := range pageItems {
if !piece.IsContinuation {
return false
}
}
return true
}
// GroupConsecutiveContinuations groups consecutive pages where next page only contains continuations
func GroupConsecutiveContinuations(pieces PiecesByPage) GroupedPiecesByPage {
grouped := GroupedPiecesByPage{
Items: make(map[int][]GroupedPieceByIssue),
// CreateIndividualPagesWithMetadata creates individual page entries with metadata
func CreateIndividualPagesWithMetadata(pieces PiecesByPage, lib *xmlmodels.Library) IndividualPiecesByPage {
individual := IndividualPiecesByPage{
Items: make(map[int][]IndividualPieceByIssue),
Pages: []int{},
}
if len(pieces.Pages) == 0 {
return grouped
return individual
}
// Sort pages to ensure correct order
sortedPages := make([]int, len(pieces.Pages))
copy(sortedPages, pieces.Pages)
slices.Sort(sortedPages)
processedPages := make(map[int]bool)
for _, page := range sortedPages {
if processedPages[page] {
continue
}
// Process each page individually
for _, page := range pieces.Pages {
pageItems := pieces.Items[page]
startPage := page
endPage := page
// Keep extending the group while next page contains only continuations
for checkPage := endPage + 1; ; checkPage++ {
// Only proceed if this page exists in our data
if _, exists := pieces.Items[checkPage]; !exists {
break
}
// Only proceed if this page hasn't been processed yet
if processedPages[checkPage] {
break
}
checkPageItems := pieces.Items[checkPage]
// Group if the next page contains ONLY continuations
if pageContainsOnlyContinuations(checkPageItems) {
endPage = checkPage
processedPages[checkPage] = true
// Continue to check if next page also contains only continuations
} else {
break
}
}
// Create grouped items with proper ordering (continuations first)
groupedItems := []GroupedPieceByIssue{}
individualItems := []IndividualPieceByIssue{}
// First add all continuation pieces
for _, piece := range pageItems {
if piece.IsContinuation {
groupedItems = append(groupedItems, GroupedPieceByIssue{
individualPiece := IndividualPieceByIssue{
PieceByIssue: piece,
StartPage: startPage,
EndPage: endPage,
})
IssueRefs: getPieceIssueRefs(piece.Piece, lib),
PageIcon: determinePageIcon(page, pieces.Pages),
}
individualItems = append(individualItems, individualPiece)
}
}
// Then add all non-continuation pieces
for _, piece := range pageItems {
if !piece.IsContinuation {
groupedItems = append(groupedItems, GroupedPieceByIssue{
individualPiece := IndividualPieceByIssue{
PieceByIssue: piece,
StartPage: startPage,
EndPage: endPage,
})
IssueRefs: getPieceIssueRefs(piece.Piece, lib),
PageIcon: determinePageIcon(page, pieces.Pages),
}
individualItems = append(individualItems, individualPiece)
}
}
if len(groupedItems) > 0 {
grouped.Items[startPage] = groupedItems
grouped.Pages = append(grouped.Pages, startPage)
if len(individualItems) > 0 {
individual.Items[page] = individualItems
individual.Pages = append(individual.Pages, page)
}
processedPages[page] = true
}
slices.Sort(grouped.Pages)
return grouped
slices.Sort(individual.Pages)
return individual
}
// determinePageIcon determines the icon type for a page based on newspaper layout positioning
func determinePageIcon(pageNum int, allPages []int) string {
if len(allPages) == 0 {
return "first"
}
slices.Sort(allPages)
firstPage := allPages[0]
lastPage := allPages[len(allPages)-1]
// Newspaper layout logic based on physical page positioning
if pageNum == firstPage {
return "first" // Front page - normal icon
} else if pageNum == lastPage {
return "last" // Back page - mirrored icon
} else {
// For middle pages in a 4-page newspaper layout:
// Page 2 (left side of middle spread) should be "even"
// Page 3 (right side of middle spread) should be "odd"
// But we need to consider the actual page position in layout
if pageNum == firstPage+1 {
return "even" // Page 2 - black + mirrored grey
} else if pageNum == lastPage-1 {
return "odd" // Page 3 - grey + black
} else {
// For newspapers with more than 4 pages, use alternating pattern
if pageNum%2 == 0 {
return "even"
} else {
return "odd"
}
}
}
}
// getPieceIssueRefs gets all issue references for a piece
func getPieceIssueRefs(piece xmlmodels.Piece, lib *xmlmodels.Library) []xmlmodels.IssueRef {
refs := []xmlmodels.IssueRef{}
for _, ref := range piece.IssueRefs {
refs = append(refs, ref)
}
return refs
}
// calculateGridLayout calculates grid positioning for newspaper pages
func calculateGridLayout(pages []IssuePage) []IssuePage {
if len(pages) == 0 {
return pages
}
result := make([]IssuePage, len(pages))
copy(result, pages)
for i := range result {
page := &result[i]
pageNum := i + 1 // 1-based page numbers
// Determine grid position based on newspaper layout logic
switch pageNum {
case 1:
// Page 1: Left, Row 1
page.GridColumn = 1
page.GridRow = 1
page.PageIcon = "first"
case 2, 3:
// Pages 2-3: Double spread with header, Row 2
if pageNum == 2 {
page.GridColumn = 1
page.HasHeader = true
page.HeaderText = fmt.Sprintf("%d-%d", pageNum, pageNum+1)
} else {
page.GridColumn = 2
}
page.GridRow = 2
page.PageIcon = determinePageIconForLayout(pageNum)
case 4:
// Page 4: Right, Row 3
page.GridColumn = 2
page.GridRow = 3
page.PageIcon = "last"
default:
// Handle additional pages if needed
page.GridColumn = ((pageNum - 1) % 2) + 1
page.GridRow = ((pageNum - 1) / 2) + 1
page.PageIcon = determinePageIconForLayout(pageNum)
}
}
return result
}
// determinePageIconForLayout determines icon for layout positioning
func determinePageIconForLayout(pageNum int) string {
if pageNum%2 == 0 {
return "even"
}
return "odd"
}
func LoadIssueImages(issue xmlmodels.Issue) (IssueImages, error) {
@@ -386,11 +445,18 @@ func LoadIssueImages(issue xmlmodels.Issue) (IssueImages, error) {
}
if len(beilagePages) > 0 {
// Calculate grid layout for beilage pages
beilagePages = calculateGridLayout(beilagePages)
// Use beilage number 1 as default
images.AdditionalPages[1] = beilagePages
}
}
// Calculate grid layout for main pages
if len(images.MainPages) > 0 {
images.MainPages = calculateGridLayout(images.MainPages)
}
return images, nil
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

File diff suppressed because one or more lines are too long

View File

@@ -1,3 +1,12 @@
<div class="mt-8">
<h1 class="text-2xl">Königsberger gelehrte und politische Zeitungen</h1>
<div class="pb-16 mx-auto bg-slate-50 w-full border-t-8 border-slate-600 ">
<header class="mx-auto w-fit mt-12">
<a href="/" class="no-underline">
<h1 class="text-2xl">Königsberger gelehrte und politische Zeitungen</h1>
</a>
</header>
<nav>
{{ block "_menu" . }}
{{ end }}
</nav>
</div>

View File

@@ -1,4 +1,4 @@
<div class="flex flex-row justify-center mt-8">
<div class="flex flex-row justify-center mt-12 mb-8">
<div class="w-6/12">
<input
type="search"

View File

@@ -30,30 +30,16 @@
</head>
<body class="w-full" hx-ext="response-targets" hx-boost="true">
{{ template "_header" . }}
<div class="container flex flex-col min-h-screen max-w-(--breakpoint-2xl) mx-auto">
<header>
{{ block "_header" . }}
<!-- Default app header... -->
{{ end }}
</header>
<div>
{{ block "_menu" . }}
<!-- Default app menu... -->
{{ end }}
</div>
<main class="">
{{ block "body" . }}
<!-- Default app body... -->
{{ end }}
</main>
<footer>
{{ block "_footer" . }}
{{ end }}
</footer>
</div>
{{ block "_footer" . }}
{{ end }}
{{ EmbedXSLT "xslt/transform-citation.xsl" }}
</body>

View File

@@ -32,19 +32,8 @@
<body class="w-full" hx-ext="response-targets" hx-boost="true">
<div class="flex flex-col min-h-screen">
<!-- Header and menu with constrained width -->
<div class="container max-w-(--breakpoint-2xl) mx-auto">
<header>
{{ block "_header" . }}
<!-- Default app header... -->
{{ end }}
</header>
{{ template "_header" . }}
<div>
{{ block "_menu" . }}
<!-- Default app menu... -->
{{ end }}
</div>
</div>
<!-- Main content with full width -->
<main class="flex-1 w-full">
@@ -64,4 +53,4 @@
{{ EmbedXSLT "xslt/transform-citation.xsl" }}
</body>
</html>
</html>

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

View File

@@ -2,73 +2,78 @@
{{ if $model.Images.HasImages }}
<!-- Container with proper padding -->
<div class="px-4 lg:px-6 xl:px-8">
<div class="">
<!-- Three-column layout -->
<div class="flex flex-col lg:flex-row gap-6 w-full min-h-screen mt-8">
<div class="flex flex-col lg:flex-row gap-6 w-full min-h-screen">
<!-- Column 1: Sticky Inhaltsverzeichnis -->
<div class="lg:w-1/4 xl:w-1/5 flex-shrink-0">
<div class="lg:sticky lg:top-12 lg:max-h-[calc(100vh-2rem)] lg:overflow-y-auto">
{{ template "_title_nav" . }}
{{ template "_inhaltsverzeichnis" . }}
<div class="lg:w-1/4 xl:w-1/5 flex-shrink-0 bg-slate-50 px-8 py-4">
<div class="lg:sticky lg:top-8 lg:overflow-y-auto">
<div class="bg-slate-50">
{{ template "_title_nav" . }}
</div>
<div class="">
{{ template "_inhaltsverzeichnis" . }}
</div>
</div>
</div>
<!-- Column 2: Newspaper pages -->
<div class="lg:w-3/5 xl:w-3/5 flex-1">
<div class="lg:w-3/5 xl:w-3/5 flex-1 py-4">
{{ template "_newspaper_layout" . }}
</div>
<!-- Column 3: Navigation buttons -->
<div class="w-16 lg:w-20 xl:w-24 flex-shrink-0">
<div class="w-16 lg:w-20 xl:w-24 flex-shrink-0 ">
<div class="lg:sticky lg:top-12 lg:max-h-[calc(100vh-2rem)]">
<div class="space-y-3 flex flex-col items-center px-2 pt-8">
<button
id="prevPageBtn"
onclick="scrollToPreviousPage()"
class="w-14 h-10 lg:w-16 lg:h-12 px-2 py-1 bg-gray-200 hover:bg-gray-300 text-gray-700 hover:text-gray-800 border border-gray-300 transition-colors duration-200 flex items-center justify-center cursor-pointer"
title="Vorherige Seite"
style="display: none;">
<i class="ri-arrow-up-line text-lg lg:text-xl"></i>
</button>
<button
id="prevPageBtn"
onclick="scrollToPreviousPage()"
class="w-14 h-10 lg:w-16 lg:h-12 px-2 py-1 bg-gray-200 hover:bg-gray-300 text-gray-700 hover:text-gray-800 border border-gray-300 transition-colors duration-200 flex items-center justify-center cursor-pointer"
title="Vorherige Seite"
style="display: none;">
<i class="ri-arrow-up-line text-lg lg:text-xl"></i>
</button>
<button
id="nextPageBtn"
onclick="scrollToNextPage()"
class="w-14 h-10 lg:w-16 lg:h-12 px-2 py-1 bg-gray-200 hover:bg-gray-300 text-gray-700 hover:text-gray-800 border border-gray-300 transition-colors duration-200 flex items-center justify-center cursor-pointer"
title="Nächste Seite">
<i class="ri-arrow-down-line text-lg lg:text-xl"></i>
</button>
<button
id="nextPageBtn"
onclick="scrollToNextPage()"
class="w-14 h-10 lg:w-16 lg:h-12 px-2 py-1 bg-gray-200 hover:bg-gray-300 text-gray-700 hover:text-gray-800 border border-gray-300 transition-colors duration-200 flex items-center justify-center cursor-pointer"
title="Nächste Seite">
<i class="ri-arrow-down-line text-lg lg:text-xl"></i>
</button>
{{ if $model.AdditionalPieces.Pages }}
<button
id="beilageBtn"
onclick="scrollToBeilage()"
class="w-14 h-10 lg:w-16 lg:h-12 px-2 py-1 bg-amber-100 hover:bg-amber-200 text-amber-700 hover:text-amber-800 border border-amber-300 transition-colors duration-200 flex items-center justify-center cursor-pointer"
title="Zu Beilage">
<i class="ri-attachment-line text-lg lg:text-xl"></i>
</button>
{{ end }}
{{ if $model.HasBeilageButton }}
<button
id="beilageBtn"
onclick="scrollToBeilage()"
class="w-14 h-10 lg:w-16 lg:h-12 px-2 py-1 bg-amber-100 hover:bg-amber-200 text-amber-700 hover:text-amber-800 border border-amber-300 transition-colors duration-200 flex items-center justify-center cursor-pointer"
title="Zu Beilage">
<i class="ri-attachment-line text-lg lg:text-xl"></i>
</button>
{{ end }}
<!-- Separator for utility buttons -->
<div class="w-full border-t border-gray-200 my-4"></div>
<!-- Share Link Button -->
<button
id="shareLinkBtn"
onclick="shareCurrentPage()"
class="w-14 h-10 lg:w-16 lg:h-12 px-2 py-1 bg-blue-100 hover:bg-blue-200 text-blue-700 hover:text-blue-800 border border-blue-300 transition-colors duration-200 flex items-center justify-center cursor-pointer"
title="Link zur aktuellen Seite teilen">
<i class="ri-share-line text-lg lg:text-xl"></i>
</button>
<!-- Separator for utility buttons -->
<div class="w-full border-t border-gray-200 my-4"></div>
<!-- Citation Button -->
<button
id="citationBtn"
onclick="generateCitation()"
class="w-14 h-10 lg:w-16 lg:h-12 px-2 py-1 bg-green-100 hover:bg-green-200 text-green-700 hover:text-green-800 border border-green-300 transition-colors duration-200 flex items-center justify-center cursor-pointer"
title="Zitation für diese Seite generieren">
<i class="ri-file-text-line text-lg lg:text-xl"></i>
</button>
<!-- Share Link Button -->
<button
id="shareLinkBtn"
onclick="shareCurrentPage()"
class="w-14 h-10 lg:w-16 lg:h-12 px-2 py-1 bg-blue-100 hover:bg-blue-200 text-blue-700 hover:text-blue-800 border border-blue-300 transition-colors duration-200 flex items-center justify-center cursor-pointer"
title="Link zur aktuellen Seite teilen">
<i class="ri-share-line text-lg lg:text-xl"></i>
</button>
<!-- Citation Button -->
<button
id="citationBtn"
onclick="generateCitation()"
class="w-14 h-10 lg:w-16 lg:h-12 px-2 py-1 bg-green-100 hover:bg-green-200 text-green-700 hover:text-green-800 border border-green-300 transition-colors duration-200 flex items-center justify-center cursor-pointer"
title="Zitation für diese Seite generieren">
<i class="ri-file-text-line text-lg lg:text-xl"></i>
</button>
</div>
</div>
</div>

View File

@@ -8,52 +8,65 @@
<i class="ri-file-list-3-line text-slate-600"></i>
<h3 class="text-base font-semibold text-slate-800">Inhalt</h3>
</div>
{{ range $page := $model.Pieces.Pages }}
<div class="mb-6 first:mb-0 pl-4 border-l-4 border-slate-300" data-page-container="{{ $page }}">
{{ range $page := $model.Pieces.Pages }}
{{ $pageItems := (index $model.Pieces.Items $page) }}
{{ $firstItem := index $pageItems 0 }}
<!-- Individual page entry -->
<div
class="mb-6 first:mb-0 pl-4 border-l-4 border-slate-300 page-entry"
data-page-container="{{ $page }}">
<div class="flex items-center justify-between gap-2 mb-2">
<div class="flex items-center gap-2">
{{ $allPages := $model.Pieces.Pages }}
{{ $firstPage := index $allPages 0 }}
{{ $lastPageIndex := sub (len $allPages) 1 }}
{{ $lastPage := index $allPages $lastPageIndex }}
{{ if eq $page $firstPage }}
<i class="ri-file-text-line text-black text-sm"></i>
{{ else if eq $page $lastPage }}
<i class="ri-file-text-line text-black text-sm" style="transform: scaleX(-1);"></i>
{{ else }}
{{ $isEvenPage := eq (mod $page 2) 0 }}
{{ if $isEvenPage }}
<i class="ri-file-text-line text-black text-sm" style="transform: scaleX(-1); margin-right: -8px;"></i><i class="ri-file-text-line text-slate-400 text-sm"></i>
{{ else }}
<i class="ri-file-text-line text-slate-400 text-sm" style="transform: scaleX(-1); margin-right: -8px;"></i><i class="ri-file-text-line text-black text-sm"></i>
{{ end }}
{{ end }}
{{ $pageItems := (index $model.Pieces.Items $page) }}
{{ $maxEndPage := $page }}
{{ range $groupedPiece := $pageItems }}{{ if gt $groupedPiece.EndPage $maxEndPage }}{{ $maxEndPage = $groupedPiece.EndPage }}{{ end }}{{ end }}
<a href="#page-{{ $page }}" class="page-number-inhalts font-bold text-slate-700 bg-blue-50 px-2 py-1 rounded text-sm transition-colors duration-200 hover:bg-blue-100 no-underline" data-page-number="{{ $page }}" data-end-page="{{ $maxEndPage }}" data-page-range="{{ $page }}-{{ $maxEndPage }}">{{ if ne $page $maxEndPage }}{{ $page }}-{{ $maxEndPage }}{{ else }}{{ $page }}{{ end }}</a>
<span class="icon-container">{{ PageIcon $firstItem.PageIcon }}</span>
<a
href="#page-{{ $page }}"
class="page-number-inhalts font-bold text-slate-700 bg-blue-50 px-2 py-1 rounded text-sm transition-colors duration-200 hover:bg-blue-100 no-underline"
data-page-number="{{ $page }}">
<span class="page-label">{{ $page }}</span>
</a>
</div>
<button class="page-permalink-btn text-slate-400 hover:text-blue-600 text-xs p-1 rounded hover:bg-blue-50 transition-colors duration-200"
title="Link zu dieser Seite kopieren"
onclick="copyPagePermalink('{{ $page }}', this)"
data-page="{{ $page }}">
<button
class="page-permalink-btn text-slate-400 hover:text-blue-600 text-xs p-1 rounded hover:bg-blue-50 transition-colors duration-200"
title="Link zu dieser Seite kopieren"
onclick="copyPagePermalink('{{ $page }}', this)"
data-page="{{ $page }}">
<i class="ri-link text-sm"></i>
</button>
</div>
<!-- Content area -->
<div class="space-y-0">
{{ range $groupedPiece := (index $model.Pieces.Items $page) }}
<div class="inhalts-entry py-1 px-0 bg-slate-50 rounded hover:bg-slate-100 transition-colors duration-200{{ if $groupedPiece.PieceByIssue.IsContinuation }} continuation-entry hidden{{ end }}" data-page="{{ $page }}"{{ if $groupedPiece.PieceByIssue.IsContinuation }} data-is-continuation="true"{{ end }}>
{{ template "_inhaltsverzeichnis_eintrag" $groupedPiece.PieceByIssue }}
{{ range $individualPiece := $pageItems }}
<div
class="inhalts-entry py-1 px-0 bg-slate-50 rounded hover:bg-slate-100 transition-colors duration-200 {{ if $individualPiece.PieceByIssue.IsContinuation }}
continuation-entry
{{ end }}"
data-page="{{ $page }}"
{{ if $individualPiece.PieceByIssue.IsContinuation }}
data-is-continuation="true"
{{ end }}
style="{{ if $individualPiece.PieceByIssue.IsContinuation }}
display: none;
{{ end }}">
{{ template "_inhaltsverzeichnis_eintrag" $individualPiece.PieceByIssue }}
<!-- Links zu anderen Teilen: -->
{{ if and (not $groupedPiece.PieceByIssue.IsContinuation) (gt (len $groupedPiece.IssueRefs) 1) }}
{{ if and (not $individualPiece.PieceByIssue.IsContinuation) (gt (len $individualPiece.IssueRefs) 1) }}
<div class="mt-1 pt-1 border-t border-slate-100">
<div class="flex items-center flex-wrap gap-1">
<i class="ri-links-line text-blue-500 text-sm mr-1"></i>
{{ range $issue := $groupedPiece.IssueRefs }}
{{ range $issue := $individualPiece.IssueRefs }}
<a
href="/{{- $issue.When -}}/{{- $issue.Nr -}}{{- if $issue.Von -}}{{- if $issue.Beilage -}}#beilage-{{ $issue.Beilage }}-page-{{ $issue.Von }}{{- else -}}#page-{{ $issue.Von }}{{- end -}}{{- end -}}"
href="/{{- $issue.When -}}/{{- $issue.Nr -}}{{- if $issue.Von -}}
{{- if $issue.Beilage -}}
#beilage-{{ $issue.Beilage }}-page-{{ $issue.Von }}
{{- else -}}
#page-{{ $issue.Von }}
{{- end -}}
{{- end -}}"
class="inline-flex items-center gap-1 px-2 py-1 bg-blue-50 text-blue-700 rounded-md text-xs font-medium hover:bg-blue-100 transition-colors duration-150"
{{- if and (eq $issue.Nr $model.Number.No) (eq $issue.When.Year
$model.Datum.When.Year)
@@ -61,18 +74,16 @@
aria-current="page"
{{ end }}>
<i class="ri-calendar-line text-xs"></i>
{{- $issue.When.Year }} Nr. {{ $issue.Nr -}}
{{- $issue.When.Year }} Nr.
{{ $issue.Nr -}}
</a>
{{ end }}
</div>
</div>
{{ end }}
</div>
</div>
{{ end }}
<!-- Pages end -->
</div>
</div>
</div>
{{- end -}}
</div>
@@ -86,52 +97,67 @@
<i class="ri-attachment-line text-amber-600"></i>
<h3 class="text-base font-semibold text-slate-800">Beilage</h3>
</div>
{{ range $page := $model.AdditionalPieces.Pages }}
<div class="mb-6 first:mb-0 pl-4 border-l-4 border-amber-400" data-page-container="{{ $page }}" data-beilage="true">
{{ range $page := $model.AdditionalPieces.Pages }}
{{ $pageItems := (index $model.AdditionalPieces.Items $page) }}
{{ $firstItem := index $pageItems 0 }}
<!-- Individual beilage page entry -->
<div
class="mb-6 first:mb-0 pl-4 border-l-4 border-amber-400 page-entry"
data-page-container="{{ $page }}"
data-beilage="true">
<div class="flex items-center justify-between gap-2 mb-2">
<div class="flex items-center gap-2">
{{ $allBeilagePages := $model.AdditionalPieces.Pages }}
{{ $firstBeilagePage := index $allBeilagePages 0 }}
{{ $lastBeilagePageIndex := sub (len $allBeilagePages) 1 }}
{{ $lastBeilagePage := index $allBeilagePages $lastBeilagePageIndex }}
{{ if eq $page $firstBeilagePage }}
<i class="ri-file-text-line text-amber-600 text-sm"></i>
{{ else if eq $page $lastBeilagePage }}
<i class="ri-file-text-line text-amber-600 text-sm" style="transform: scaleX(-1);"></i>
{{ else }}
{{ $isEvenPage := eq (mod $page 2) 0 }}
{{ if $isEvenPage }}
<i class="ri-file-text-line text-amber-600 text-sm" style="transform: scaleX(-1); margin-right: -8px;"></i><i class="ri-file-text-line text-slate-400 text-sm"></i>
{{ else }}
<i class="ri-file-text-line text-slate-400 text-sm" style="transform: scaleX(-1); margin-right: -8px;"></i><i class="ri-file-text-line text-amber-600 text-sm"></i>
{{ end }}
{{ end }}
{{ $pageItems := (index $model.AdditionalPieces.Items $page) }}
{{ $maxEndPage := $page }}
{{ range $groupedPiece := $pageItems }}{{ if gt $groupedPiece.EndPage $maxEndPage }}{{ $maxEndPage = $groupedPiece.EndPage }}{{ end }}{{ end }}
<a href="#beilage-1-page-{{ $page }}" class="page-number-inhalts font-bold text-slate-700 bg-amber-50 px-2 py-1 rounded text-sm transition-colors duration-200 hover:bg-amber-100 no-underline" data-page-number="{{ $page }}" data-end-page="{{ $maxEndPage }}" data-page-range="{{ $page }}-{{ $maxEndPage }}">{{ if ne $page $maxEndPage }}{{ $page }}-{{ $maxEndPage }}{{ else }}{{ $page }}{{ end }}</a>
<span class="icon-container">{{ PageIcon $firstItem.PageIcon }}</span>
<a
href="#beilage-1-page-{{ $page }}"
class="page-number-inhalts font-bold text-slate-700 bg-amber-50 px-2 py-1 rounded text-sm transition-colors duration-200 hover:bg-amber-100 no-underline"
data-page-number="{{ $page }}">
<span class="page-label">{{ $page }}</span>
</a>
</div>
<button class="page-permalink-btn text-slate-400 hover:text-amber-600 text-xs p-1 rounded hover:bg-amber-50 transition-colors duration-200"
title="Link zu dieser Seite kopieren"
onclick="copyPagePermalink('{{ $page }}', this, true)"
data-page="{{ $page }}" data-beilage="true">
<button
class="page-permalink-btn text-slate-400 hover:text-amber-600 text-xs p-1 rounded hover:bg-amber-50 transition-colors duration-200"
title="Link zu dieser Seite kopieren"
onclick="copyPagePermalink('{{ $page }}', this, true)"
data-page="{{ $page }}"
data-beilage="true">
<i class="ri-link text-sm"></i>
</button>
</div>
<div class="space-y-1">
{{ range $groupedPiece := (index $model.AdditionalPieces.Items $page) }}
<div class="inhalts-entry py-2 px-0 bg-slate-50 rounded hover:bg-slate-100 transition-colors duration-200{{ if $groupedPiece.PieceByIssue.IsContinuation }} continuation-entry hidden{{ end }}" data-page="{{ $page }}"{{ if $groupedPiece.PieceByIssue.IsContinuation }} data-is-continuation="true"{{ end }}>
{{ template "_inhaltsverzeichnis_eintrag" $groupedPiece.PieceByIssue }}
<!-- Content area -->
<div class="space-y-0">
{{ range $individualPiece := $pageItems }}
<div
class="inhalts-entry py-1 px-0 bg-slate-50 rounded hover:bg-slate-100 transition-colors duration-200 {{ if $individualPiece.PieceByIssue.IsContinuation }}
continuation-entry
{{ end }}"
data-page="{{ $page }}"
{{ if $individualPiece.PieceByIssue.IsContinuation }}
data-is-continuation="true"
{{ end }}
style="{{ if $individualPiece.PieceByIssue.IsContinuation }}
display: none;
{{ end }}">
{{ template "_inhaltsverzeichnis_eintrag" $individualPiece.PieceByIssue }}
<!-- Links zu anderen Teilen: -->
{{ if and (not $groupedPiece.PieceByIssue.IsContinuation) (gt (len $groupedPiece.IssueRefs) 1) }}
{{ if and (not $individualPiece.PieceByIssue.IsContinuation) (gt (len $individualPiece.IssueRefs) 1) }}
<div class="mt-1 pt-1 border-t border-slate-100">
<div class="flex items-center flex-wrap gap-1">
<i class="ri-links-line text-blue-500 text-sm mr-1"></i>
{{ range $issue := $groupedPiece.IssueRefs }}
{{ range $issue := $individualPiece.IssueRefs }}
<a
href="/{{- $issue.When -}}/{{- $issue.Nr -}}{{- if $issue.Von -}}{{- if $issue.Beilage -}}#beilage-{{ $issue.Beilage }}-page-{{ $issue.Von }}{{- else -}}#page-{{ $issue.Von }}{{- end -}}{{- end -}}"
href="/{{- $issue.When -}}/{{- $issue.Nr -}}{{- if $issue.Von -}}
{{- if $issue.Beilage -}}
#beilage-{{ $issue.Beilage }}-page-{{ $issue.Von }}
{{- else -}}
#page-{{ $issue.Von }}
{{- end -}}
{{- end -}}"
class="inline-flex items-center gap-1 px-2 py-1 bg-blue-50 text-blue-700 rounded-md text-xs font-medium hover:bg-blue-100 transition-colors duration-150"
{{- if and (eq $issue.Nr $model.Number.No) (eq $issue.When.Year
$model.Datum.When.Year)
@@ -139,18 +165,16 @@
aria-current="page"
{{ end }}>
<i class="ri-calendar-line text-xs"></i>
{{- $issue.When.Year }} Nr. {{ $issue.Nr -}}
{{- $issue.When.Year }} Nr.
{{ $issue.Nr -}}
</a>
{{ end }}
</div>
</div>
{{ end }}
</div>
</div>
{{ end }}
<!-- Pages end -->
</div>
</div>
</div>
{{- end -}}
</div>

View File

@@ -1,292 +1,510 @@
{{- $piece := . -}}
{{- $fortsPrefix := "" -}}
{{- if $piece.IsContinuation -}}{{- $fortsPrefix = "<span class=\"italic text-gray-600\">(Forts.) </span>" -}}{{- end -}}
{{- if $piece.IsContinuation -}}
{{- $fortsPrefix = "<span class=\"italic text-gray-600\">(Forts.) </span>" -}}
{{- end -}}
<div class="entry-description leading-snug mb-1">
{{- $hasRezension := false -}}
{{- $hasWeltnachrichten := false -}}
{{- $hasEinkommendeFremde := false -}}
{{- $hasWechselkurse := false -}}
{{- $hasBuecher := false -}}
{{- $hasLokalanzeigen := false -}}
{{- $hasLokalnachrichten := false -}}
{{- $hasLotterie := false -}}
{{- $hasGedicht := false -}}
{{- $hasVorladung := false -}}
{{- $hasAuszug := false -}}
{{- $hasAufsatz := false -}}
{{- $hasGelehrteNachrichten := false -}}
{{- $hasTheaterkritik := false -}}
{{- $hasUebersetzung := false -}}
{{- $hasKommentar := false -}}
{{- $hasNachruf := false -}}
{{- $hasReplik := false -}}
{{- $hasProklamation := false -}}
{{- $hasIneigenersache := false -}}
{{- $hasBrief := false -}}
{{- $hasAnzeige := false -}}
{{- $hasDesertionsliste := false -}}
{{- $hasNotenblatt := false -}}
{{- $hasVorlesungsverzeichnis := false -}}
{{- $hasErzaehlung := false -}}
{{- $hasNachtrag := false -}}
{{- $hasPanegyrik := false -}}
{{- $hasKriminalanzeige := false -}}
{{- $hasAbbildung := false -}}
{{- $hasRezepte := false -}}
{{- $hasKorrektur := false -}}
{{- $hasRezension := false -}}
{{- $hasWeltnachrichten := false -}}
{{- $hasEinkommendeFremde := false -}}
{{- $hasWechselkurse := false -}}
{{- $hasBuecher := false -}}
{{- $hasLokalanzeigen := false -}}
{{- $hasLokalnachrichten := false -}}
{{- $hasLotterie := false -}}
{{- $hasGedicht := false -}}
{{- $hasVorladung := false -}}
{{- $hasAuszug := false -}}
{{- $hasAufsatz := false -}}
{{- $hasGelehrteNachrichten := false -}}
{{- $hasTheaterkritik := false -}}
{{- $hasUebersetzung := false -}}
{{- $hasKommentar := false -}}
{{- $hasNachruf := false -}}
{{- $hasReplik := false -}}
{{- $hasProklamation := false -}}
{{- $hasIneigenersache := false -}}
{{- $hasBrief := false -}}
{{- $hasAnzeige := false -}}
{{- $hasDesertionsliste := false -}}
{{- $hasNotenblatt := false -}}
{{- $hasVorlesungsverzeichnis := false -}}
{{- $hasErzaehlung := false -}}
{{- $hasNachtrag := false -}}
{{- $hasPanegyrik := false -}}
{{- $hasKriminalanzeige := false -}}
{{- $hasAbbildung := false -}}
{{- $hasRezepte := false -}}
{{- $hasKorrektur := false -}}
{{- range $catref := $piece.CategoryRefs -}}
{{- if eq $catref.Ref "rezension" -}}{{- $hasRezension = true -}}{{- end -}}
{{- if eq $catref.Ref "weltnachrichten" -}}{{- $hasWeltnachrichten = true -}}{{- end -}}
{{- if eq $catref.Ref "einkommende-fremde" -}}{{- $hasEinkommendeFremde = true -}}{{- end -}}
{{- if eq $catref.Ref "wechselkurse" -}}{{- $hasWechselkurse = true -}}{{- end -}}
{{- if eq $catref.Ref "buecher" -}}{{- $hasBuecher = true -}}{{- end -}}
{{- if eq $catref.Ref "lokalanzeigen" -}}{{- $hasLokalanzeigen = true -}}{{- end -}}
{{- if eq $catref.Ref "lokalnachrichten" -}}{{- $hasLokalnachrichten = true -}}{{- end -}}
{{- if eq $catref.Ref "lotterie" -}}{{- $hasLotterie = true -}}{{- end -}}
{{- if eq $catref.Ref "gedicht" -}}{{- $hasGedicht = true -}}{{- end -}}
{{- if eq $catref.Ref "vorladung" -}}{{- $hasVorladung = true -}}{{- end -}}
{{- if eq $catref.Ref "auszug" -}}{{- $hasAuszug = true -}}{{- end -}}
{{- if eq $catref.Ref "aufsatz" -}}{{- $hasAufsatz = true -}}{{- end -}}
{{- if eq $catref.Ref "gelehrte-nachrichten" -}}{{- $hasGelehrteNachrichten = true -}}{{- end -}}
{{- if eq $catref.Ref "theaterkritik" -}}{{- $hasTheaterkritik = true -}}{{- end -}}
{{- if eq $catref.Ref "uebersetzung" -}}{{- $hasUebersetzung = true -}}{{- end -}}
{{- if eq $catref.Ref "kommentar" -}}{{- $hasKommentar = true -}}{{- end -}}
{{- if eq $catref.Ref "nachruf" -}}{{- $hasNachruf = true -}}{{- end -}}
{{- if eq $catref.Ref "replik" -}}{{- $hasReplik = true -}}{{- end -}}
{{- if eq $catref.Ref "proklamation" -}}{{- $hasProklamation = true -}}{{- end -}}
{{- if eq $catref.Ref "ineigenersache" -}}{{- $hasIneigenersache = true -}}{{- end -}}
{{- if eq $catref.Ref "brief" -}}{{- $hasBrief = true -}}{{- end -}}
{{- if eq $catref.Ref "anzeige" -}}{{- $hasAnzeige = true -}}{{- end -}}
{{- if eq $catref.Ref "desertionsliste" -}}{{- $hasDesertionsliste = true -}}{{- end -}}
{{- if eq $catref.Ref "notenblatt" -}}{{- $hasNotenblatt = true -}}{{- end -}}
{{- if eq $catref.Ref "vorlesungsverzeichnis" -}}{{- $hasVorlesungsverzeichnis = true -}}{{- end -}}
{{- if eq $catref.Ref "erzaehlung" -}}{{- $hasErzaehlung = true -}}{{- end -}}
{{- if eq $catref.Ref "nachtrag" -}}{{- $hasNachtrag = true -}}{{- end -}}
{{- if eq $catref.Ref "panegyrik" -}}{{- $hasPanegyrik = true -}}{{- end -}}
{{- if eq $catref.Ref "kriminalanzeige" -}}{{- $hasKriminalanzeige = true -}}{{- end -}}
{{- if eq $catref.Ref "abbildung" -}}{{- $hasAbbildung = true -}}{{- end -}}
{{- if eq $catref.Ref "rezepte" -}}{{- $hasRezepte = true -}}{{- end -}}
{{- if eq $catref.Ref "korrektur" -}}{{- $hasKorrektur = true -}}{{- end -}}
{{- end -}}
{{- range $workref := $piece.WorkRefs -}}
{{- $kat := $workref.Category -}}
{{- if not $kat -}}{{- $kat = "rezension" -}}{{- end -}}
{{- if eq $kat "rezension" -}}{{- $hasRezension = true -}}{{- end -}}
{{- if eq $kat "auszug" -}}{{- $hasAuszug = true -}}{{- end -}}
{{- if eq $kat "theaterkritik" -}}{{- $hasTheaterkritik = true -}}{{- end -}}
{{- if eq $kat "uebersetzung" -}}{{- $hasUebersetzung = true -}}{{- end -}}
{{- if eq $kat "kommentar" -}}{{- $hasKommentar = true -}}{{- end -}}
{{- if eq $kat "anzeige" -}}{{- $hasAnzeige = true -}}{{- end -}}
{{- if eq $kat "replik" -}}{{- $hasReplik = true -}}{{- end -}}
{{- end -}}
{{- $place := "" -}}
{{- if $piece.PlaceRefs -}}
{{- $placeObj := GetPlace (index $piece.PlaceRefs 0).Ref -}}
{{- if gt (len $placeObj.Names) 0 -}}
{{- $place = index $placeObj.Names 0 -}}
{{- range $catref := $piece.CategoryRefs -}}
{{- if eq $catref.Ref "rezension" -}}{{- $hasRezension = true -}}{{- end -}}
{{- if eq $catref.Ref "weltnachrichten" -}}{{- $hasWeltnachrichten = true -}}{{- end -}}
{{- if eq $catref.Ref "einkommende-fremde" -}}{{- $hasEinkommendeFremde = true -}}{{- end -}}
{{- if eq $catref.Ref "wechselkurse" -}}{{- $hasWechselkurse = true -}}{{- end -}}
{{- if eq $catref.Ref "buecher" -}}{{- $hasBuecher = true -}}{{- end -}}
{{- if eq $catref.Ref "lokalanzeigen" -}}{{- $hasLokalanzeigen = true -}}{{- end -}}
{{- if eq $catref.Ref "lokalnachrichten" -}}{{- $hasLokalnachrichten = true -}}{{- end -}}
{{- if eq $catref.Ref "lotterie" -}}{{- $hasLotterie = true -}}{{- end -}}
{{- if eq $catref.Ref "gedicht" -}}{{- $hasGedicht = true -}}{{- end -}}
{{- if eq $catref.Ref "vorladung" -}}{{- $hasVorladung = true -}}{{- end -}}
{{- if eq $catref.Ref "auszug" -}}{{- $hasAuszug = true -}}{{- end -}}
{{- if eq $catref.Ref "aufsatz" -}}{{- $hasAufsatz = true -}}{{- end -}}
{{- if eq $catref.Ref "gelehrte-nachrichten" -}}
{{- $hasGelehrteNachrichten = true -}}
{{- end -}}
{{- if eq $catref.Ref "theaterkritik" -}}{{- $hasTheaterkritik = true -}}{{- end -}}
{{- if eq $catref.Ref "uebersetzung" -}}{{- $hasUebersetzung = true -}}{{- end -}}
{{- if eq $catref.Ref "kommentar" -}}{{- $hasKommentar = true -}}{{- end -}}
{{- if eq $catref.Ref "nachruf" -}}{{- $hasNachruf = true -}}{{- end -}}
{{- if eq $catref.Ref "replik" -}}{{- $hasReplik = true -}}{{- end -}}
{{- if eq $catref.Ref "proklamation" -}}{{- $hasProklamation = true -}}{{- end -}}
{{- if eq $catref.Ref "ineigenersache" -}}{{- $hasIneigenersache = true -}}{{- end -}}
{{- if eq $catref.Ref "brief" -}}{{- $hasBrief = true -}}{{- end -}}
{{- if eq $catref.Ref "anzeige" -}}{{- $hasAnzeige = true -}}{{- end -}}
{{- if eq $catref.Ref "desertionsliste" -}}{{- $hasDesertionsliste = true -}}{{- end -}}
{{- if eq $catref.Ref "notenblatt" -}}{{- $hasNotenblatt = true -}}{{- end -}}
{{- if eq $catref.Ref "vorlesungsverzeichnis" -}}
{{- $hasVorlesungsverzeichnis = true -}}
{{- end -}}
{{- if eq $catref.Ref "erzaehlung" -}}{{- $hasErzaehlung = true -}}{{- end -}}
{{- if eq $catref.Ref "nachtrag" -}}{{- $hasNachtrag = true -}}{{- end -}}
{{- if eq $catref.Ref "panegyrik" -}}{{- $hasPanegyrik = true -}}{{- end -}}
{{- if eq $catref.Ref "kriminalanzeige" -}}{{- $hasKriminalanzeige = true -}}{{- end -}}
{{- if eq $catref.Ref "abbildung" -}}{{- $hasAbbildung = true -}}{{- end -}}
{{- if eq $catref.Ref "rezepte" -}}{{- $hasRezepte = true -}}{{- end -}}
{{- if eq $catref.Ref "korrektur" -}}{{- $hasKorrektur = true -}}{{- end -}}
{{- end -}}
{{- end -}}
{{- $title := "" -}}
{{- if $piece.Title -}}
{{- $title = index $piece.Title 0 -}}
{{- else if $piece.Incipit -}}
{{- $title = index $piece.Incipit 0 -}}
{{- end -}}
{{- $workTitle := "" -}}
{{- $workAuthorName := "" -}}
{{- $workAuthorID := "" -}}
{{- if $piece.WorkRefs -}}
{{- $work := GetWork (index $piece.WorkRefs 0).Ref -}}
{{- if $work.PreferredTitle -}}
{{- $workTitle = $work.PreferredTitle -}}
{{- else if $work.Citation.Title -}}
{{- $workTitle = $work.Citation.Title -}}
{{- else if $work.Citation.Chardata -}}
{{- $workTitle = $work.Citation.Chardata -}}
{{- range $workref := $piece.WorkRefs -}}
{{- $kat := $workref.Category -}}
{{- if not $kat -}}{{- $kat = "rezension" -}}{{- end -}}
{{- if eq $kat "rezension" -}}{{- $hasRezension = true -}}{{- end -}}
{{- if eq $kat "auszug" -}}{{- $hasAuszug = true -}}{{- end -}}
{{- if eq $kat "theaterkritik" -}}{{- $hasTheaterkritik = true -}}{{- end -}}
{{- if eq $kat "uebersetzung" -}}{{- $hasUebersetzung = true -}}{{- end -}}
{{- if eq $kat "kommentar" -}}{{- $hasKommentar = true -}}{{- end -}}
{{- if eq $kat "anzeige" -}}{{- $hasAnzeige = true -}}{{- end -}}
{{- if eq $kat "replik" -}}{{- $hasReplik = true -}}{{- end -}}
{{- end -}}
{{- /* Get work author */ -}}
{{- if $work.AgentRefs -}}
{{- range $workAgentRef := $work.AgentRefs -}}
{{- if (or (eq $workAgentRef.Category "") (eq $workAgentRef.Category "autor")) -}}
{{- $workAgent := GetAgent $workAgentRef.Ref -}}
{{- if and $workAgent (gt (len $workAgent.Names) 0) -}}
{{- $workAuthorName = index $workAgent.Names 0 -}}
{{- $workAuthorID = $workAgentRef.Ref -}}
{{- break -}}
{{- $place := "" -}}
{{- if $piece.PlaceRefs -}}
{{- $placeObj := GetPlace (index $piece.PlaceRefs 0).Ref -}}
{{- if gt (len $placeObj.Names) 0 -}}
{{- $place = index $placeObj.Names 0 -}}
{{- end -}}
{{- end -}}
{{- $title := "" -}}
{{- if $piece.Title -}}
{{- $title = index $piece.Title 0 -}}
{{- else if $piece.Incipit -}}
{{- $title = index $piece.Incipit 0 -}}
{{- end -}}
{{- $workTitle := "" -}}
{{- $workTitleFull := "" -}}
{{- $workAuthorName := "" -}}
{{- $workAuthorID := "" -}}
{{- if $piece.WorkRefs -}}
{{- $work := GetWork (index $piece.WorkRefs 0).Ref -}}
{{- /* Determine short title (PreferredTitle) and full title (Citation.Title) */ -}}
{{- if $work.PreferredTitle -}}
{{- $workTitle = $work.PreferredTitle -}}
{{- else if $work.Citation.Title -}}
{{- $workTitle = $work.Citation.Title -}}
{{- else if $work.Citation.Chardata -}}
{{- $workTitle = $work.Citation.Chardata -}}
{{- end -}}
{{- /* Always get full title for highlighted state */ -}}
{{- if $work.Citation.Title -}}
{{- $workTitleFull = $work.Citation.Title -}}
{{- else if $work.Citation.Chardata -}}
{{- $workTitleFull = $work.Citation.Chardata -}}
{{- else if $work.PreferredTitle -}}
{{- $workTitleFull = $work.PreferredTitle -}}
{{- end -}}
{{- /* Get work author */ -}}
{{- if $work.AgentRefs -}}
{{- range $workAgentRef := $work.AgentRefs -}}
{{- if (or (eq $workAgentRef.Category "") (eq $workAgentRef.Category "autor")) -}}
{{- $workAgent := GetAgent $workAgentRef.Ref -}}
{{- if and $workAgent (gt (len $workAgent.Names) 0) -}}
{{- $workAuthorName = index $workAgent.Names 0 -}}
{{- $workAuthorID = $workAgentRef.Ref -}}
{{- break -}}
{{- end -}}
{{- end -}}
{{- end -}}
{{- end -}}
{{- end -}}
{{- end -}}
{{- /* Generate natural text descriptions */ -}}
{{- /* Generate natural text descriptions */ -}}
{{- if $hasRezension -}}
{{- $authorFound := false -}}
{{- range $agentref := $piece.AgentRefs -}}
{{- if (or (eq $agentref.Category "") (eq $agentref.Category "autor")) -}}
{{- $agent := GetAgent $agentref.Ref -}}
{{- if and $agent (gt (len $agent.Names) 0) -}}
{{ Safe $fortsPrefix }}<a href="/akteure/{{ $agentref.Ref }}" class="author-link">{{ index $agent.Names 0 }}</a>{{ if $workTitle }}, Rezension: <em>{{ $workTitle }}</em>{{ if $workAuthorName }}{{ if $workAuthorID }} von <a href="/akteure/{{ $workAuthorID }}" class="author-link">{{ $workAuthorName }}</a>{{ else }} von {{ $workAuthorName }}{{ end }}{{ end }}{{ else if $title }}, Rezension: <em>{{ $title }}</em>{{ else }}, Rezension{{ end }}{{ if $place }} ({{ $place }}){{ end }}
{{- $authorFound = true -}}
{{- break -}}
{{- if $hasRezension -}}
{{- $authorFound := false -}}
{{- range $agentref := $piece.AgentRefs -}}
{{- if (or (eq $agentref.Category "") (eq $agentref.Category "autor")) -}}
{{- $agent := GetAgent $agentref.Ref -}}
{{- if and $agent (gt (len $agent.Names) 0) -}}
{{ Safe $fortsPrefix }}<a href="/akteure/{{ $agentref.Ref }}" class="author-link"
>{{ index $agent.Names 0 }}</a
>,
<span class="review-format"
>Rezension von:
{{ if $workAuthorName }}
{{- if $workAuthorID -}}
<a href="/akteure/{{ $workAuthorID }}" class="author-link">{{ $workAuthorName }}</a>
{{- else -}}
{{ $workAuthorName }}
{{- end -}},
{{ end }}
{{ if $workTitle }}
<em
class="work-title"
data-short-title="{{ $workTitle }}"
{{ if $workTitleFull }}data-full-title="{{ $workTitleFull }}"{{ end }}
>{{ $workTitle }}</em
>
{{ else if $title }}
<em>{{ $title }}</em>
{{ else }}
[Werk unbekannt]
{{ end }}{{ if $place }}({{ $place }}){{ end }}</span
>
{{- $authorFound = true -}}
{{- break -}}
{{- end -}}
{{- end -}}
{{- end -}}
{{- end -}}
{{- if not $authorFound -}}
{{ Safe $fortsPrefix }}Rezension{{ if $workTitle }}: <em>{{ $workTitle }}</em>{{ if $workAuthorName }}{{ if $workAuthorID }} von <a href="/akteure/{{ $workAuthorID }}" class="author-link">{{ $workAuthorName }}</a>{{ else }} von {{ $workAuthorName }}{{ end }}{{ end }}{{ else if $title }}: <em>{{ $title }}</em>{{ end }}{{ if $place }} ({{ $place }}){{ end }}
{{- end -}}
{{- if not $authorFound -}}
{{ Safe $fortsPrefix }}<span class="review-format"
>Rezension von:
{{ if $workAuthorName }}
{{- if $workAuthorID -}}
<a href="/akteure/{{ $workAuthorID }}" class="author-link">{{ $workAuthorName }}</a>
{{- else -}}
{{ $workAuthorName }}
{{- end -}},
{{ end }}
{{ if $workTitle }}
<em
class="work-title"
data-short-title="{{ $workTitle }}"
{{ if $workTitleFull }}data-full-title="{{ $workTitleFull }}"{{ end }}
>{{ $workTitle }}</em
>
{{ else if $title }}
<em>{{ $title }}</em>
{{ else }}
[Werk unbekannt]
{{ end }}{{ if $place }}({{ $place }}){{ end }}</span
>
{{- end -}}
{{- else if $hasWeltnachrichten -}}
{{ Safe $fortsPrefix }}Politische Nachrichten aus aller Welt
{{- else if $hasWeltnachrichten -}}
{{ Safe $fortsPrefix }}Politische Nachrichten aus aller Welt
{{- else if $hasEinkommendeFremde -}}
{{- if $hasLokalnachrichten -}}
Lokale Meldungen über einreisende Fremde
{{- else if $hasNachruf -}}
Nachruf und Einreiseliste
{{- else -}}
Einreiseliste
{{- end -}}
{{ if $place }}für {{ $place }}{{ end }}
{{- else if $hasEinkommendeFremde -}}
{{- if $hasLokalnachrichten -}}Lokale Meldungen über einreisende Fremde{{- else if $hasNachruf -}}Nachruf und Einreiseliste{{- else -}}Einreiseliste{{- end -}}{{ if $place }} für {{ $place }}{{ end }}
{{- else if $hasWechselkurse -}}
Wechselkurse{{ if $place }}in {{ $place }}{{ end }}
{{- else if $hasWechselkurse -}}
Wechselkurse{{ if $place }} in {{ $place }}{{ end }}
{{- else if $hasBuecher -}}
Bücheranzeigen{{ if $title }}: <em>{{ $title }}</em>{{ end }}
{{- else if $hasBuecher -}}
Bücheranzeigen{{ if $title }}: <em>{{ $title }}</em>{{ end }}
{{- else if $hasLokalanzeigen -}}
{{ if $hasNachruf }}
Todesanzeige
{{ else }}
Lokalanzeige
{{ end }}
{{ if $place }}aus {{ $place }}{{ end }}{{ if $title }}: <em>{{ $title }}</em>{{ end }}
{{- else if $hasLokalanzeigen -}}
{{ if $hasNachruf }}Todesanzeige{{ else }}Lokalanzeige{{ end }}{{ if $place }} aus {{ $place }}{{ end }}{{ if $title }}: <em>{{ $title }}</em>{{ end }}
{{- else if $hasLokalnachrichten -}}
{{ if $hasLotterie }}
Lotterienachrichten
{{ else if $hasNachruf }}
Nachrufe
{{ else if $hasTheaterkritik }}
Theaternachrichten
{{ else if $hasPanegyrik }}
Festlichkeiten
{{ else }}
Lokalnachrichten
{{ end }}
{{ if $place }}aus {{ $place }}{{ end }}
{{- else if $hasLokalnachrichten -}}
{{ if $hasLotterie }}Lotterienachrichten{{ else if $hasNachruf }}Nachrufe{{ else if $hasTheaterkritik }}Theaternachrichten{{ else if $hasPanegyrik }}Festlichkeiten{{ else }}Lokalnachrichten{{ end }}{{ if $place }} aus {{ $place }}{{ end }}
{{- else if $hasGedicht -}}
{{- $authorFound := false -}}
{{- range $agentref := $piece.AgentRefs -}}
{{- if (or (eq $agentref.Category "") (eq $agentref.Category "autor")) -}}
{{- $agent := GetAgent $agentref.Ref -}}
{{- if and $agent (gt (len $agent.Names) 0) -}}
<a href="/akteure/{{ $agentref.Ref }}" class="author-link">{{ index $agent.Names 0 }}</a>, {{ if $hasKommentar }}Gedicht mit Kommentar{{ else if $hasUebersetzung }}Gedichtübersetzung{{ else if $hasGelehrteNachrichten }}Gedicht zu gelehrten Angelegenheiten{{ else }}Gedicht{{ end }}{{ if $title }}: <em>„{{ $title }}"</em>{{ end }}
{{- $authorFound = true -}}
{{- break -}}
{{- else if $hasGedicht -}}
{{- $authorFound := false -}}
{{- range $agentref := $piece.AgentRefs -}}
{{- if (or (eq $agentref.Category "") (eq $agentref.Category "autor")) -}}
{{- $agent := GetAgent $agentref.Ref -}}
{{- if and $agent (gt (len $agent.Names) 0) -}}
<a href="/akteure/{{ $agentref.Ref }}" class="author-link">{{ index $agent.Names 0 }}</a>,
{{ if $hasKommentar }}
Gedicht mit Kommentar
{{ else if $hasUebersetzung }}
Gedichtübersetzung
{{ else if $hasGelehrteNachrichten }}
Gedicht zu gelehrten Angelegenheiten
{{ else }}
Gedicht
{{ end }}{{ if $title }}: <em>„{{ $title }}"</em>{{ end }}
{{- $authorFound = true -}}
{{- break -}}
{{- end -}}
{{- end -}}
{{- end -}}
{{- end -}}
{{- if not $authorFound -}}
{{ if $hasKommentar }}Gedicht mit Kommentar{{ else if $hasUebersetzung }}Gedichtübersetzung{{ else if $hasGelehrteNachrichten }}Gedicht zu gelehrten Angelegenheiten{{ else }}Gedicht{{ end }}{{ if $title }}: <em>„{{ $title }}"</em>{{ end }}
{{- end -}}
{{- if not $authorFound -}}
{{ if $hasKommentar }}
Gedicht mit Kommentar
{{ else if $hasUebersetzung }}
Gedichtübersetzung
{{ else if $hasGelehrteNachrichten }}
Gedicht zu gelehrten Angelegenheiten
{{ else }}
Gedicht
{{ end }}{{ if $title }}: <em>„{{ $title }}"</em>{{ end }}
{{- end -}}
{{- else if $hasVorladung -}}
Gerichtliche Vorladung{{ if $place }} in {{ $place }}{{ end }}{{ if $title }}: <em>{{ $title }}</em>{{ end }}
{{- else if $hasVorladung -}}
Gerichtliche
Vorladung{{ if $place }}in {{ $place }}{{ end }}{{ if $title }}: <em>{{ $title }}</em>{{ end }}
{{- else if $hasAufsatz -}}
{{- $authorFound := false -}}
{{- range $agentref := $piece.AgentRefs -}}
{{- if (or (eq $agentref.Category "") (eq $agentref.Category "autor")) -}}
{{- $agent := GetAgent $agentref.Ref -}}
{{- if and $agent (gt (len $agent.Names) 0) -}}
{{ Safe $fortsPrefix }}<a href="/akteure/{{ $agentref.Ref }}" class="author-link">{{ index $agent.Names 0 }}</a>, {{ if $hasReplik }}Erwiderung{{ else if $hasUebersetzung }}Übersetzung{{ else if $hasNachruf }}Nachruf{{ else if $hasKommentar }}Kommentar{{ else if $hasRezepte }}Rezepte und Anleitungen{{ else }}Aufsatz{{ end }}{{ if $title }}: <em>„{{ $title }}"</em>{{ end }}
{{- $authorFound = true -}}
{{- break -}}
{{- else if $hasAufsatz -}}
{{- $authorFound := false -}}
{{- range $agentref := $piece.AgentRefs -}}
{{- if (or (eq $agentref.Category "") (eq $agentref.Category "autor")) -}}
{{- $agent := GetAgent $agentref.Ref -}}
{{- if and $agent (gt (len $agent.Names) 0) -}}
{{ Safe $fortsPrefix }}<a href="/akteure/{{ $agentref.Ref }}" class="author-link"
>{{ index $agent.Names 0 }}</a
>,
{{ if $hasReplik }}
Erwiderung
{{ else if $hasUebersetzung }}
Übersetzung
{{ else if $hasNachruf }}
Nachruf
{{ else if $hasKommentar }}
Kommentar
{{ else if $hasRezepte }}
Rezepte und Anleitungen
{{ else }}
Aufsatz
{{ end }}{{ if $title }}: <em>„{{ $title }}"</em>{{ end }}
{{- $authorFound = true -}}
{{- break -}}
{{- end -}}
{{- end -}}
{{- end -}}
{{- end -}}
{{- if not $authorFound -}}
{{ Safe $fortsPrefix }}{{ if $hasReplik }}Erwiderung{{ else if $hasUebersetzung }}Übersetzung{{ else if $hasNachruf }}Nachruf{{ else if $hasKommentar }}Kommentar{{ else if $hasRezepte }}Rezepte und Anleitungen{{ else }}Aufsatz{{ end }}{{ if $title }}: <em>„{{ $title }}"</em>{{ end }}
{{- end -}}
{{- if not $authorFound -}}
{{ Safe $fortsPrefix }}{{ if $hasReplik }}
Erwiderung
{{ else if $hasUebersetzung }}
Übersetzung
{{ else if $hasNachruf }}
Nachruf
{{ else if $hasKommentar }}
Kommentar
{{ else if $hasRezepte }}
Rezepte und Anleitungen
{{ else }}
Aufsatz
{{ end }}{{ if $title }}: <em>„{{ $title }}"</em>{{ end }}
{{- end -}}
{{- else if $hasGelehrteNachrichten -}}
{{ Safe $fortsPrefix }}{{ if $hasTheaterkritik }}Theaterkritik{{ else if $hasKommentar }}Gelehrter Kommentar{{ else }}Gelehrte Nachrichten{{ end }}{{ if $place }} aus {{ $place }}{{ end }}
{{- else if $hasGelehrteNachrichten -}}
{{ Safe $fortsPrefix }}{{ if $hasTheaterkritik }}
Theaterkritik
{{ else if $hasKommentar }}
Gelehrter Kommentar
{{ else }}
Gelehrte Nachrichten
{{ end }}
{{ if $place }}aus {{ $place }}{{ end }}
{{- else if $hasTheaterkritik -}}
{{- $authorFound := false -}}
{{- range $agentref := $piece.AgentRefs -}}
{{- if (or (eq $agentref.Category "") (eq $agentref.Category "autor")) -}}
{{- $agent := GetAgent $agentref.Ref -}}
{{- if and $agent (gt (len $agent.Names) 0) -}}
{{ Safe $fortsPrefix }}<a href="/akteure/{{ $agentref.Ref }}" class="author-link">{{ index $agent.Names 0 }}</a>, Theaterkritik{{ if $workTitle }} zu <em>{{ $workTitle }}</em>{{ if $workAuthorName }} von <a href="/akteure/{{ $workAuthorID }}" class="author-link">{{ $workAuthorName }}</a>{{ end }}{{ else if $title }} zu <em>{{ $title }}</em>{{ end }}{{ if $place }} ({{ $place }}){{ end }}
{{- $authorFound = true -}}
{{- break -}}
{{- else if $hasTheaterkritik -}}
{{- $authorFound := false -}}
{{- range $agentref := $piece.AgentRefs -}}
{{- if (or (eq $agentref.Category "") (eq $agentref.Category "autor")) -}}
{{- $agent := GetAgent $agentref.Ref -}}
{{- if and $agent (gt (len $agent.Names) 0) -}}
{{ Safe $fortsPrefix }}<a href="/akteure/{{ $agentref.Ref }}" class="author-link"
>{{ index $agent.Names 0 }}</a
>,
Theaterkritik{{ if $workTitle }}
zu <em>{{ $workTitle }}</em>{{ if $workAuthorName }}
von
<a href="/akteure/{{ $workAuthorID }}" class="author-link">{{ $workAuthorName }}</a>
{{ end }}
{{ else if $title }}
zu <em>{{ $title }}</em>
{{ end }}{{ if $place }}({{ $place }}){{ end }}
{{- $authorFound = true -}}
{{- break -}}
{{- end -}}
{{- end -}}
{{- end -}}
{{- end -}}
{{- if not $authorFound -}}
{{ Safe $fortsPrefix }}Theaterkritik{{ if $workTitle }} zu <em>{{ $workTitle }}</em>{{ if $workAuthorName }} von <a href="/akteure/{{ $workAuthorID }}" class="author-link">{{ $workAuthorName }}</a>{{ end }}{{ else if $title }} zu <em>{{ $title }}</em>{{ end }}{{ if $place }} ({{ $place }}){{ end }}
{{- end -}}
{{- if not $authorFound -}}
{{ Safe $fortsPrefix }}Theaterkritik{{ if $workTitle }}
zu <em>{{ $workTitle }}</em>{{ if $workAuthorName }}
von <a href="/akteure/{{ $workAuthorID }}" class="author-link">{{ $workAuthorName }}</a>
{{ end }}
{{ else if $title }}
zu <em>{{ $title }}</em>
{{ end }}{{ if $place }}({{ $place }}){{ end }}
{{- end -}}
{{- else if $hasProklamation -}}
{{ Safe $fortsPrefix }}Amtliche Proklamation{{ if $title }}: <em>{{ $title }}</em>{{ end }}
{{- else if $hasProklamation -}}
{{ Safe $fortsPrefix }}Amtliche
Proklamation{{ if $title }}: <em>{{ $title }}</em>{{ end }}
{{- else if $hasIneigenersache -}}
{{ Safe $fortsPrefix }}{{ if $hasKommentar }}{{ if $hasNachtrag }}Ergänzender Kommentar{{ else }}Redaktioneller Kommentar{{ end }}{{ else if $hasReplik }}Redaktionelle Stellungnahme{{ else }}Anmerkung der Redaktion{{ end }}{{ if $title }}: <em>{{ $title }}</em>{{ end }}
{{- else if $hasIneigenersache -}}
{{ Safe $fortsPrefix }}{{ if $hasKommentar }}
{{ if $hasNachtrag }}Ergänzender Kommentar{{ else }}Redaktioneller Kommentar{{ end }}
{{ else if $hasReplik }}
Redaktionelle Stellungnahme
{{ else }}
Anmerkung der Redaktion
{{ end }}
{{ if $title }}: <em>{{ $title }}</em>{{ end }}
{{- else if $hasBrief -}}
{{ Safe $fortsPrefix }}{{ if $hasNachruf }}Kondolenzbrief{{ else }}Leserbrief{{ end }}{{- $authorFound := false -}}{{- range $agentref := $piece.AgentRefs -}}{{- if (or (eq $agentref.Category "") (eq $agentref.Category "autor")) -}}{{- $agent := GetAgent $agentref.Ref -}}{{- if and $agent (gt (len $agent.Names) 0) -}} von <a href="/akteure/{{ $agentref.Ref }}" class="author-link">{{ index $agent.Names 0 }}</a>{{- $authorFound = true -}}{{- break -}}{{- end -}}{{- end -}}{{- end -}}{{ if $place }} aus {{ $place }}{{ end }}
{{- else if $hasBrief -}}
{{ Safe $fortsPrefix }}{{ if $hasNachruf }}
Kondolenzbrief
{{ else }}
Leserbrief
{{ end }}
{{- $authorFound := false -}}{{- range $agentref := $piece.AgentRefs -}}
{{- if (or (eq $agentref.Category "") (eq $agentref.Category "autor")) -}}
{{- $agent := GetAgent $agentref.Ref -}}{{- if and $agent (gt (len $agent.Names) 0) -}}
von
<a href="/akteure/{{ $agentref.Ref }}" class="author-link">{{ index $agent.Names 0 }}</a
>{{- $authorFound = true -}}{{- break -}}
{{- end -}}
{{- else if $hasDesertionsliste -}}
{{ Safe $fortsPrefix }}Desertionsliste{{ if $place }} für {{ $place }}{{ end }}
{{- end -}}
{{- else if $hasNotenblatt -}}
{{ Safe $fortsPrefix }}{{ if $hasNachtrag }}Ergänztes {{ end }}Notenblatt{{ if $title }}: <em>{{ $title }}</em>{{ end }}
{{- end -}}
{{ if $place }}aus {{ $place }}{{ end }}
{{- else if $hasVorlesungsverzeichnis -}}
{{ Safe $fortsPrefix }}Vorlesungsverzeichnis{{ if $place }} der Universität {{ $place }}{{ end }}
{{- else if $hasDesertionsliste -}}
{{ Safe $fortsPrefix }}Desertionsliste{{ if $place }}für {{ $place }}{{ end }}
{{- else if $hasErzaehlung -}}
{{- $authorFound := false -}}
{{- range $agentref := $piece.AgentRefs -}}
{{- if (or (eq $agentref.Category "") (eq $agentref.Category "autor")) -}}
{{- $agent := GetAgent $agentref.Ref -}}
{{- if and $agent (gt (len $agent.Names) 0) -}}
{{ Safe $fortsPrefix }}<a href="/akteure/{{ $agentref.Ref }}" class="author-link">{{ index $agent.Names 0 }}</a>, {{ if $hasUebersetzung }}Übersetzung einer Erzählung{{ else }}Erzählung{{ end }}{{ if $title }}: <em>„{{ $title }}"</em>{{ end }}
{{- $authorFound = true -}}
{{- break -}}
{{- else if $hasNotenblatt -}}
{{ Safe $fortsPrefix }}{{ if $hasNachtrag }}Ergänztes{{ end }}Notenblatt{{ if $title }}
: <em>{{ $title }}</em>
{{ end }}
{{- else if $hasVorlesungsverzeichnis -}}
{{ Safe $fortsPrefix }}Vorlesungsverzeichnis{{ if $place }}der Universität {{ $place }}{{ end }}
{{- else if $hasErzaehlung -}}
{{- $authorFound := false -}}
{{- range $agentref := $piece.AgentRefs -}}
{{- if (or (eq $agentref.Category "") (eq $agentref.Category "autor")) -}}
{{- $agent := GetAgent $agentref.Ref -}}
{{- if and $agent (gt (len $agent.Names) 0) -}}
{{ Safe $fortsPrefix }}<a href="/akteure/{{ $agentref.Ref }}" class="author-link"
>{{ index $agent.Names 0 }}</a
>,
{{ if $hasUebersetzung }}
Übersetzung einer Erzählung
{{ else }}
Erzählung
{{ end }}{{ if $title }}: <em>„{{ $title }}"</em>{{ end }}
{{- $authorFound = true -}}
{{- break -}}
{{- end -}}
{{- end -}}
{{- end -}}
{{- end -}}
{{- if not $authorFound -}}
{{ Safe $fortsPrefix }}{{ if $hasUebersetzung }}Übersetzung einer Erzählung{{ else }}Erzählung{{ end }}{{ if $title }}: <em>„{{ $title }}"</em>{{ end }}
{{- end -}}
{{- if not $authorFound -}}
{{ Safe $fortsPrefix }}{{ if $hasUebersetzung }}
Übersetzung einer Erzählung
{{ else }}
Erzählung
{{ end }}{{ if $title }}: <em>„{{ $title }}"</em>{{ end }}
{{- end -}}
{{- else if $hasAbbildung -}}
{{ Safe $fortsPrefix }}{{ if $hasAufsatz }}Illustrierter Aufsatz{{ else }}Abbildung{{ end }}{{ if $title }}: <em>{{ $title }}</em>{{ end }}
{{- else if $hasAbbildung -}}
{{ Safe $fortsPrefix }}{{ if $hasAufsatz }}
Illustrierter Aufsatz
{{ else }}
Abbildung
{{ end }}
{{ if $title }}: <em>{{ $title }}</em>{{ end }}
{{- else if $hasKriminalanzeige -}}
{{ Safe $fortsPrefix }}Kriminalanzeige{{ if $place }} aus {{ $place }}{{ end }}
{{- else if $hasKriminalanzeige -}}
{{ Safe $fortsPrefix }}Kriminalanzeige{{ if $place }}aus {{ $place }}{{ end }}
{{- else if $hasKorrektur -}}
{{ Safe $fortsPrefix }}Korrektur{{ if $title }}: <em>{{ $title }}</em>{{ end }}
{{- else if $hasKorrektur -}}
{{ Safe $fortsPrefix }}Korrektur{{ if $title }}: <em>{{ $title }}</em>{{ end }}
{{- else if $hasAnzeige -}}
{{ Safe $fortsPrefix }}{{ if $hasAuszug }}{{ if $hasGedicht }}Gedichtauszug{{ else }}Textauszug{{ end }}{{ else }}Anzeige{{ end }}{{ if $title }}: <em>{{ $title }}</em>{{ end }}
{{- else if $hasAnzeige -}}
{{ Safe $fortsPrefix }}{{ if $hasAuszug }}
{{ if $hasGedicht }}Gedichtauszug{{ else }}Textauszug{{ end }}
{{ else }}
Anzeige
{{ end }}
{{ if $title }}: <em>{{ $title }}</em>{{ end }}
{{- else if $hasAuszug -}}
{{ Safe $fortsPrefix }}Auszug{{ if $title }}: <em>„{{ $title }}"</em>{{ end }}{{ if $workTitle }} aus <em>{{ $workTitle }}</em>{{ if $workAuthorName }} von <a href="/akteure/{{ $workAuthorID }}" class="author-link">{{ $workAuthorName }}</a>{{ end }}{{ end }}
{{- else if $hasAuszug -}}
{{ Safe $fortsPrefix }}Auszug{{ if $title }}: <em>„{{ $title }}"</em>{{ end }}
{{ if $workTitle }}
aus <em>{{ $workTitle }}</em>{{ if $workAuthorName }}
von <a href="/akteure/{{ $workAuthorID }}" class="author-link">{{ $workAuthorName }}</a>
{{ end }}
{{- else -}}
{{- $authorFound := false -}}
{{- range $agentref := $piece.AgentRefs -}}
{{- if (or (eq $agentref.Category "") (eq $agentref.Category "autor")) -}}
{{- $agent := GetAgent $agentref.Ref -}}
{{- if and $agent (gt (len $agent.Names) 0) -}}
{{ Safe $fortsPrefix }}<a href="/akteure/{{ $agentref.Ref }}" class="author-link">{{ index $agent.Names 0 }}</a>{{ if $title }}: <em>{{ $title }}</em>{{ end }}{{ if $workTitle }}{{ if $title }} aus {{ end }}<em>{{ $workTitle }}</em>{{ if $workAuthorName }} von <a href="/akteure/{{ $workAuthorID }}" class="author-link">{{ $workAuthorName }}</a>{{ end }}{{ end }}
{{- $authorFound = true -}}
{{- break -}}
{{ end }}
{{- else -}}
{{- $authorFound := false -}}
{{- range $agentref := $piece.AgentRefs -}}
{{- if (or (eq $agentref.Category "") (eq $agentref.Category "autor")) -}}
{{- $agent := GetAgent $agentref.Ref -}}
{{- if and $agent (gt (len $agent.Names) 0) -}}
{{ Safe $fortsPrefix }}<a href="/akteure/{{ $agentref.Ref }}" class="author-link"
>{{ index $agent.Names 0 }}</a
>{{ if $title }}: <em>{{ $title }}</em>{{ end }}{{ if $workTitle }}
{{ if $title }}aus{{ end }}<em>{{ $workTitle }}</em>{{ if $workAuthorName }}
von
<a href="/akteure/{{ $workAuthorID }}" class="author-link">{{ $workAuthorName }}</a>
{{ end }}
{{ end }}
{{- $authorFound = true -}}
{{- break -}}
{{- end -}}
{{- end -}}
{{- end -}}
{{- end -}}
{{- if not $authorFound -}}
{{ Safe $fortsPrefix }}{{ if $title }}<em>{{ $title }}</em>{{ end }}{{ if $workTitle }}{{ if $title }} aus {{ end }}<em>{{ $workTitle }}</em>{{ if $workAuthorName }} von <a href="/akteure/{{ $workAuthorID }}" class="author-link">{{ $workAuthorName }}</a>{{ end }}{{ else if not $title }}Beitrag ohne Titel{{ end }}
{{- end -}}
{{- if not $authorFound -}}
{{ Safe $fortsPrefix }}{{ if $title }}<em>{{ $title }}</em>{{ end }}{{ if $workTitle }}
{{ if $title }}aus{{ end }}<em>{{ $workTitle }}</em>{{ if $workAuthorName }}
von <a href="/akteure/{{ $workAuthorID }}" class="author-link">{{ $workAuthorName }}</a>
{{ end }}
{{ else if not $title }}
Beitrag ohne Titel
{{ end }}
{{- end -}}
{{- end -}}
{{- end -}}
</div>
{{- if not $piece.IsContinuation -}}
{{- range $annotation := $piece.AnnotationNote.Annotations -}}
<div class="italic text-sm mt-0.5 text-slate-600">
{{ $annotation.Inner.InnerXML }}
</div>
{{- range $annotation := $piece.AnnotationNote.Annotations -}}
<div class="italic text-sm mt-0.5 text-slate-600">
{{ $annotation.Inner.InnerXML }}
</div>
{{- end -}}
{{- end -}}
{{- end -}}

File diff suppressed because it is too large Load Diff

View File

@@ -1,39 +1,46 @@
{{ $model := .model }}
{{ $date := .model.Datum.When }}
<div class="sticky top-4 mb-12 z-10">
<!-- Header with year link left, nav buttons right -->
<div class="flex items-center justify-between mb-3">
<a href="/jahrgang/{{- $date.Year -}}"
class="inline-flex items-center gap-1 text-black hover:text-slate-700 text-base font-medium">
<i class="ri-calendar-line"></i>
{{ $date.Year }}
</a>
<!-- Header with year link left, nav buttons right -->
<div class="flex items-center justify-between mb-3">
<a
href="/jahrgang/{{- $date.Year -}}"
class="inline-flex items-center gap-1 text-black hover:text-slate-700 text-base font-medium">
<i class="ri-calendar-line"></i>
{{ $date.Year }}
</a>
<div class="flex flex-row gap-x-1">
{{ if $model.Prev }}
<a href="/{{- $model.Prev.Datum.When.Year -}}/{{- $model.Prev.Number.No -}}"
class="inline-flex items-center justify-center w-7 h-7 bg-slate-100 text-slate-700 rounded hover:bg-slate-200 transition-colors">
<i class="ri-arrow-left-line text-sm"></i>
</a>
{{ end }}
<div class="flex flex-row gap-x-1">
{{ if $model.Prev }}
<a
href="/{{- $model.Prev.Datum.When.Year -}}/{{- $model.Prev.Number.No -}}"
class="inline-flex items-center justify-center w-7 h-7 bg-slate-100 text-slate-700 rounded
hover:bg-slate-200 transition-colors no-underline font-bold">
<i class="ri-arrow-left-line text-sm"></i>
</a>
{{ end }}
{{ if $model.Next }}
<a href="/{{- $model.Next.Datum.When.Year -}}/{{- $model.Next.Number.No -}}"
class="inline-flex items-center justify-center w-7 h-7 bg-slate-100 text-slate-700 rounded hover:bg-slate-200 transition-colors">
<i class="ri-arrow-right-line text-sm"></i>
</a>
{{ end }}
</div>
{{ if $model.Next }}
<a
href="/{{- $model.Next.Datum.When.Year -}}/{{- $model.Next.Number.No -}}"
class="inline-flex items-center justify-center w-7 h-7 bg-slate-100 text-slate-700 rounded
hover:bg-slate-200 transition-colors no-underline font-bold">
<i class="ri-arrow-right-line text-sm"></i>
</a>
{{ end }}
</div>
</div>
<!-- Issue title and date -->
<div class="border-t border-slate-200 pt-3">
<div class="flex items-center justify-between">
<div class="flex items-center gap-1">
<i class="ri-newspaper-line text-lg text-slate-600"></i>
<h1 class="text-lg font-semibold text-slate-800">{{ $date.Year }}&#8201;/&#8201;{{ $model.Number.No }}</h1>
</div>
<div class="text-base font-medium text-slate-700 bg-slate-100 px-2 py-1 rounded">{{ printf "%.2s" (WeekdayName $date.Weekday) }} {{ $date.Day }}.{{ $date.Month }}.</div>
<!-- Issue title and date -->
<div class="border-t border-slate-200 pt-3 mb-4">
<div class="flex items-center justify-between">
<div class="flex items-center gap-1">
<h1 class="text-lg font-semibold text-slate-800">
{{ $model.Number.No }}&#8201;/&#8201;{{ $date.Year }}
</h1>
</div>
<div class="text-base font-medium text-slate-700 bg-slate-100 px-2 py-1 rounded">
<span class="pr-1">{{ printf "%.2s" (WeekdayName $date.Weekday) }}</span>
<b>{{ $date.Day }}. {{ $date.MonthNameShort }}</b>
</div>
</div>
</div>

View File

@@ -4,6 +4,35 @@
--font-script: Rancho, ui-serif;
--font-sans: "Source Sans 3", "Merriweather Sans", ui-sans-serif;
--font-serif: "Merriweather", ui-serif;
/* Custom Black Colors */
--color-abyss: #0b1215;
--color-shadow: #0f171f;
--color-eclipse: #0b0b0b;
--color-storm: #020c1a;
--color-deep: #011122;
--color-obsidian: #161616;
}
/* Alternative approach using pseudo-element for better browser support */
body::before {
content: "";
position: fixed;
/* Extend beyond viewport to ensure full coverage after transformations */
top: -50%;
left: -50%;
right: -50%;
bottom: -50%;
z-index: -1;
/* Your WebP pattern */
background-image: url("skyscraper.webp");
background-size: 100px 100px;
background-repeat: repeat;
background-position: center;
/* Apply transformations here */
transform: rotate(15deg) skew(10deg) scale(3);
opacity: 0.4;
}
/*