diff --git a/.dockerignore b/.dockerignore index 06a9286c4..a281d2df8 100644 --- a/.dockerignore +++ b/.dockerignore @@ -5,5 +5,6 @@ dist local.build.properties node_modules libs +.existdb.json .github **/.DS_Store diff --git a/catalogues/dictionary_de.xml b/catalogues/dictionary_de.xml index de9148e5b..9a63237dd 100644 --- a/catalogues/dictionary_de.xml +++ b/catalogues/dictionary_de.xml @@ -149,7 +149,12 @@ überschrieben durchgestrichen und ersetzt mit überschrieben mit + durch Nummerierung der Wörter umgestellt zu gelöscht + Hand + Hände + Haupthand + Weitere Hände in der Vorlage weitere mögliche Lesungen Abk. von @@ -442,6 +447,7 @@ Diese Seite kann in Ihrem Browser nicht korrekt dargestellt werden. Zur besseren Darstellung aktualisieren Sie bitte den Browser. Inhaltsverzeichnis + Inhalt Bibliographie Discographie Literatur diff --git a/catalogues/dictionary_en.xml b/catalogues/dictionary_en.xml index eb89c92e0..3a5fa7118 100644 --- a/catalogues/dictionary_en.xml +++ b/catalogues/dictionary_en.xml @@ -147,7 +147,12 @@ overwritten crossed out and replaced with overwritten with + by numbering the words rearranged to erased + Hand + Hands + Main hand + Further hands in the copy text further possible transcriptions Abbreviation @@ -412,6 +417,7 @@ Your Browser doesn't support JavaScript or it is currently disabled. Since our site heavily relies on it we have to apologize for this inconvenience! This Website won't display correctly in your browser. It is necessary to update your browser to display the data correctly. Table of contents + Content Bibliography Discography Literature @@ -651,4 +657,4 @@ Mountain, Hill, Rock Forest, Heath WeGA full texts - \ No newline at end of file + diff --git a/modules/app.xqm b/modules/app.xqm index 5833eba5f..7241e68bd 100644 --- a/modules/app.xqm +++ b/modules/app.xqm @@ -493,6 +493,28 @@ declare } }; +(: + : set the active tab in documents, sources, letters etc. + : switch between text and editorial depending on the presence of a transcription + : + : @author Steffen Astheimer + : @return the input node with adapted class attributes ('active' for nav tabs, 'active in' for tab panes) + :) +declare function app:set-tab-state($node as node(), $model as map(*)) as element() { + let $target := if(exists($node/@href)) then substring-after($node/@href, '#') else string($node/@id) + let $isTabPane := exists($node/@id) + let $isActive := ($target = 'transcription' and $model('hasTranscription')) or ($target = 'editorial' and not($model('hasTranscription'))) + let $newClass := + if($isActive) then string-join((($node/@class, if($isTabPane) then 'in' else ()), 'active'), ' ') + else string($node/@class) + return + element {node-name($node)} { + $node/@*[not(name(.) = 'class')], + attribute class {$newClass}, + templates:process($node/node(), $model) + } +}; + (:~ : set the maximum dates for the IonRangeSlider ~:) @@ -1328,10 +1350,22 @@ declare function app:print-external-data-disclaimer($node as node(), $model as m declare %templates:wrap function app:doc-details($node as node(), $model as map(*)) as map(*) { + let $doc := $model('doc') + let $lang := $model('lang') let $facs := query:facsimile($model?doc) let $localFacsimiles := $facs[tei:graphic][not(@sameAs)] except $facs[tei:graphic[starts-with(@url, 'http')]] let $externalIIIFManifestFacsimiles := $facs[@sameAs] let $IIIFImagesMap := ($localFacsimiles | $externalIIIFManifestFacsimiles) ! app:create-IIIFImagesMap(., $model) + let $docType := $model('docType') + let $textRoot := + switch($docType) + case 'diaries' return $doc/tei:ab ! app:inject-query(.) + case 'works' return $doc/mei:mei ! app:inject-query(.) + case 'var' case 'addenda' return ($doc//tei:text/tei:body ! app:inject-query(.))/(tei:div[@xml:lang=$lang] | tei:divGen | tei:div[not(@xml:lang)]) + case 'thematicCommentaries' return $doc//tei:text/tei:body ! app:inject-query(.) | $doc//tei:text/tei:back + case 'sources' return $doc//tei:text ! app:inject-query(.) + default return $doc//tei:text/tei:body ! app:inject-query(.) + let $hasTranscription := not(functx:all-whitespace({$textRoot})) return map { 'facsimile' : $facs, @@ -1339,6 +1373,8 @@ declare 'externalIIIFManifestFacsimiles' : $externalIIIFManifestFacsimiles, 'IIIFImagesMap': $IIIFImagesMap, 'hasCreation' : exists($model?doc//tei:creation), + 'hasTranscription' : $hasTranscription, + 'textRoot' : $textRoot, 'xml-download-url' : replace(controller:create-url-for-doc($model('doc'), $model('lang')), '\.html', '.xml'), 'thematicCommentaries' : distinct-values($model('doc')//tei:note[@type='thematicCom']/@target/tokenize(., '\s+')), 'backlinks' : wdt:backlinks(())('filter-by-person')($model?docID) @@ -1397,17 +1433,12 @@ declare case 'works' return doc(concat($config:xsl-collection-path, '/works.xsl')) case 'writings' case 'documents' return doc(concat($config:xsl-collection-path, '/document.xsl')) case 'diaries' return doc(concat($config:xsl-collection-path, '/diaries.xsl')) + case 'sources' return doc(concat($config:xsl-collection-path, '/sources.xsl')) default return doc(concat($config:xsl-collection-path, '/var.xsl')) - let $textRoot := - switch($docType) - case 'diaries' return $doc/tei:ab ! app:inject-query(.) - case 'works' return $doc/mei:mei ! app:inject-query(.) - case 'var' case 'addenda' return ($doc//tei:text/tei:body ! app:inject-query(.))/(tei:div[@xml:lang=$lang] | tei:divGen | tei:div[not(@xml:lang)]) - case 'thematicCommentaries' return $doc//tei:text/tei:body ! app:inject-query(.) | $doc//tei:text/tei:back - default return $doc//tei:text/tei:body ! app:inject-query(.) + let $textRoot := $model('textRoot') let $body := - if(functx:all-whitespace({$textRoot})) - then + if(not($model('hasTranscription'))) + then element xhtml:p { attribute class {'notAvailable'}, (: revealed correspondence which has backlinks gets a direct link to the backlinks, see https://github.com/Edirom/WeGA-WebApp/issues/304 :) @@ -1430,7 +1461,6 @@ declare let $foot := if(config:is-news($docID)) then app:get-news-foot($doc, $lang) else () - return map { 'transcription' : (wega-util:remove-elements-by-class($body, 'apparatus'),$foot), @@ -1438,6 +1468,34 @@ declare } }; +(:~ + : Create a table of contents for nested headers of sources + : based on the sources.xsl transformation from app:prepare-text()#2 + : + : @author Steffen Astheimer + : @return an xhtml:ul with a list of anchors, categorized by header nesting level + :) +declare function app:doc-toc($node as node(), $model as map(*)) as element()* { + element xhtml:ul { + for $head in $model('transcription')//xhtml:h2[contains-token(@class, 'srcHeader')] + let $classTokens := tokenize(normalize-space(string($head/@class)), '\s+') + let $levelToken := ($classTokens[starts-with(., 'header-level-')])[1] + let $level := if ($levelToken) then substring-after($levelToken, 'header-level-') else '1' + let $tocClass := 'toc-level-' || $level + let $id := normalize-space(string($head/@id)) + let $label := normalize-space(string-join($head//text()[not(ancestor::xhtml:a)], '')) + where $id != '' and $label != '' + return + element xhtml:li { + attribute class { $tocClass }, + element xhtml:a { + attribute href { '#' || $id }, + $label + } + } + } +}; + (:~ : Search and highlight query strings in a document : Helper function for app:prepare-text() @@ -1728,7 +1786,8 @@ declare %templates:default("lang", "en") %templates:wrap function app:print-context-relatedItem-type($node as node(), $model as map(*), $lang as xs:string) as xs:string? { - lang:get-language-string($model?context-relatedItem?context-relatedItem-type, $lang) + let $type := $model?context-relatedItem?context-relatedItem-type + return if(exists($type)) then lang:get-language-string($model?context-relatedItem?context-relatedItem-type, $lang) else () }; (:~ diff --git a/modules/query.xqm b/modules/query.xqm index b1a948699..eab875c09 100644 --- a/modules/query.xqm +++ b/modules/query.xqm @@ -286,7 +286,7 @@ declare function query:text-sources($doc as document-node()) as element()* { Umwandlung der Dauerleihgabe in eine Schenkung durch Hans-Jürgen Freiherr von Weber am 15. November 1986 - case 'works' case 'sources' return () (:$model('doc')//mei:sourceDesc:) + case 'works' return () (:$model('doc')//mei:sourceDesc:) case 'biblio' return $doc/tei:biblStruct default return $doc//tei:sourceDesc/tei:* return @@ -606,7 +606,7 @@ declare function query:witness-facsimile($source as element()) as element(tei:fa : The value of this key is a sequence of maps, each containing the keys 'context-relatedItem-type', 'context-relatedItem-doc' and 'context-relatedItem-n' ~:) declare function query:context-relatedItems($doc as document-node()?) as map(*)? { - let $relatedItems := + let $teiRelatedItems := for $relatedItem in $doc//tei:notesStmt/tei:relatedItem return map { @@ -614,6 +614,16 @@ declare function query:context-relatedItems($doc as document-node()?) as map(*)? 'context-relatedItem-doc': crud:doc(substring-after($relatedItem/@target, ':')), 'context-relatedItem-n': data($relatedItem/@n) } + let $meiWeGAIdentifiers := + for $WeGAIdentifier in $doc/mei:manifestation/mei:identifier[@type = 'WeGA'] + let $key := normalize-space(string($WeGAIdentifier)) + return + map { + 'context-relatedItem-type': (), (: no equivalent in current data :) + 'context-relatedItem-doc': crud:doc($key), + 'context-relatedItem-n': () (: no equivalent in current data :) + } + let $relatedItems := ($teiRelatedItems, $meiWeGAIdentifiers) return if(exists($relatedItems)) then map { diff --git a/resources/sass/components/_popover.scss b/resources/sass/components/_popover.scss index b9e4e9b2f..52bb970ff 100644 --- a/resources/sass/components/_popover.scss +++ b/resources/sass/components/_popover.scss @@ -44,6 +44,18 @@ float:left; margin-bottom: 4px; } + .hand { + display: block; + margin-top: 6px; + font-style: italic; + font-size: .7rem; + &::before { + content: "("; + } + &::after { + content: ")"; + } + } } .carousel-indicators { bottom: -45px!important; diff --git a/resources/sass/components/_tei.scss b/resources/sass/components/_tei.scss index ecf392740..43471cdd3 100644 --- a/resources/sass/components/_tei.scss +++ b/resources/sass/components/_tei.scss @@ -94,7 +94,7 @@ $tei_list-indent: $font-size-base; } div.poem { - margin: 0.5pc 0em 0.5pc 10%; + margin: 0.5pc 0em 0.5pc 10%; } div.poem h2 { @@ -115,10 +115,6 @@ div.poem h3 { text-align: center; } -.verseLine { - display: block; -} - .tei_code { font-family: monospace; } @@ -171,9 +167,9 @@ li.listSubTitle { } } -/* - und werden als 'block' gesetzt, - damit die Textausrichtung (s.u.) modifiziert werden kann +/* + und werden als 'block' gesetzt, + damit die Textausrichtung (s.u.) modifiziert werden kann */ .tei_signed, .tei_segBlock { display: block; @@ -191,8 +187,8 @@ li.listSubTitle { text-align: left; } -/* set titles of biblio entries in italics and - * set neste tei_hi_italic in normal shape +/* set titles of biblio entries in italics and + * set neste tei_hi_italic in normal shape */ .biblio-entry { .title, .journalTitle, .collectionTitle { @@ -243,7 +239,7 @@ li.listSubTitle { } /* - * address within div/@type="address" + * address within div/@type="address" */ .teiLetter_address { margin-bottom:$line-height-computed; @@ -251,7 +247,7 @@ li.listSubTitle { } /* - * address within closer + * address within closer */ .tei_closer .tei_address { margin-top:$line-height-computed; @@ -289,3 +285,291 @@ li.listSubTitle { .tei_dateline { display:block; } + +/* libretti */ +.teiSrc_text { + --page-width: min(50ch, 92vw); + --indent: 5ch; + --lg-indent-amount: 0; + --l-indent-amount: 0; + + max-width: var(--page-width); + margin: 0 auto; + text-align: center; + + /* styling for page breaks – a mix from WeGA diaries and HenDi page breaks */ + hr.tei_pb-text { + width: var(--page-width); + max-width: none; + margin: 3rem 0; + position: relative; + left: 50%; + transform: translateX(-50%); + + border: 0; + border-top: 2px solid var(--primary); + border-radius: 5px; + + &::after { + content: attr(data-content); + position: absolute; + text-indent: initial; + left: 50%; + top: 0; + transform: translate(-50%, -50%); + padding: 0 1rem; + + background: #fff; + color: var(--primary); + font-size: .8rem; + font-style: italic; + } + } + + /* some block level elements */ + .tei_titlePart, + .tei_castList, + .tei_caption, + .tei_speaker, + [class^="lg"], + [class^="verseLine"], + [class^="tei_stage"] { + display: block; + } + + /* some default alignment overwrite */ + p { + text-align: justify; + } + .tei_subst + .tei_subst::before { + content: " "; + } + + .teiSrc_front { + .tei_titlePage { + .tei_titlePart { + margin: 1.5rem; + line-height: 2.5; + } + } + .tei_castList { + position: relative; + line-height: 2; + margin-bottom: 1rem; + + .tei_castItem { + display: grid; + grid-template-columns: auto auto 1fr auto; + column-gap: .4em; + width: 100%; + text-align: left; + + .tei_role { + grid-column: 1; + } + .tei_roleDesc { + grid-column: 2; + } + .tei_leader_dots { + grid-column: 3; + border-bottom: 2.5px dotted; + transform: translateY(-0.5em); + } + .tei_actor { + grid-column: 4; + justify-self: end; + } + } + + /* styling for cast groups with optional brackets to the right */ + [class^="tei_castGroup"] { + display: grid; + grid-template-columns: auto auto auto 1fr auto; + column-gap: .4rem; + width: 100%; + + > .tei_castItem { + display: contents; + + .tei_role { + grid-column: 1 + } + .tei_leader_dots { + grid-column: 4; + border-bottom: 2.5px dotted; + transform: translateY(-0.5em); + } + .tei_actor { + grid-column: 5; + justify-self: end; + } + } + .tei_roleDesc { + grid-column: 3; + grid-row: 1 / 999; + display: flex; + align-items: center; + justify-content: flex-start; + } + } + .tei_castGroup_braced { + &::before { + content: ""; + grid-column: 2; + grid-row: 1 / 999; + align-self: stretch; + justify-self: center; + /* draw a brace for castGroups */ + width: 1rem; + border: 2px solid #000; + border-left: none; + border-radius: 0 1rem 1rem 0; + margin: .8rem 0; + } + } + } + } + + .teiSrc_body { + /* general page layout, spacing, and indenting */ + .tei_sp { + [class^="lg"] { + margin: 0 auto; + text-align: left; + &:has(+ [class^="lg"]) { + margin-bottom: 2rem; + } + /* set lg indent modifier up to indent-5 */ + &[class*="indent"] { + &[class$="-1"] { + --lg-indent-amount: 1; + } + &[class$="-2"] { + --lg-indent-amount: 2; + } + &[class$="-3"] { + --lg-indent-amount: 3; + } + &[class$="-4"] > * { + --lg-indent-amount: 4; + } + &[class$="-5"] > * { + --lg-indent-amount: 5; + } + } + } + + /* quite hacky approach to displaying 'middle' and 'final' parts of verseLines + * basically there are two offsets on which the verseLines are aligned centrally */ + [class^="verseLine"] { + margin: 0 auto; + text-align: left; + &[class$="-M"], + &[class*="-M-"] { + margin-left: calc(var(--page-width) / 4); + } + &[class$="-F"], + &[class*="-F-"] { + margin-left: calc(var(--page-width) / 4); + text-align: center; + } + /* indenting for verseLines up to indent-5 (only on big screens) */ + @media (min-width: 530px) { + &[class*="indent"] { + &[class$="-1"] { + --l-indent-amount: 1; + } + &[class$="-2"] { + --l-indent-amount: 2; + } + &[class$="-3"] { + --l-indent-amount: 3; + } + &[class$="-4"] > * { + --l-indent-amount: 4; + } + &[class$="-5"] > * { + --l-indent-amount: 5; + } + } + text-indent: calc((var(--indent) * var(--l-indent-amount)) + (var(--indent) * var(--lg-indent-amount))); + } + } + } + + /* some more font sizes, margins and adjustments */ + [class^="tei_stage"] { + font-size: .9rem; + &[class$="_left"] { + text-align: justify; + } + &[class$="_right"] { + text-align: right; + } + } + .srcHeader { + margin-top: 1rem; + } + .header-level-act { + font-size: 3rem; + } + .tei_caption { + font-size: 1.5rem; + margin: .8rem 0; + } + .tei_speaker { + font-size: 1.1rem; + margin: .3rem 0; + } + + /* inline elements */ + .tei_speaker:has(+ .tei_stage_inline) { + display: inline; + + .tei_stage_inline { + display: inline; + margin-left: .3em; + } + } + [class^="verseLine"]:has(> .tei_stage_inline) { + display: inline-block; + text-align: left; + width: 100%; + > .tei_stage_inline { + display: inline; + } + } + + /* styling for spGrps with brackets */ + .tei_spGrp_braced-left { + display: grid; + grid-template-columns: max-content max-content auto; + align-items: stretch; + column-gap: .5rem; + + > .tei_sp { + grid-column: 3; + } + > .tei_stage_left { + grid-column: 1; + grid-row: 1 / 999; + display: flex; + align-items: center; + justify-content: center; + writing-mode: vertical-rl; + } + &::before { + content: ""; + grid-column: 2; + grid-row: 1 / 999; + align-self: stretch; + justify-self: center; + /* draw a brace for spGrps */ + width: 1rem; + background: #fff; + border: 2px solid #000; + border-right: none; + border-radius: 1rem 0 0 1rem; + } + } + } +} diff --git a/resources/sass/layout/_sidebar.scss b/resources/sass/layout/_sidebar.scss index a65fad1d0..a30cb5658 100644 --- a/resources/sass/layout/_sidebar.scss +++ b/resources/sass/layout/_sidebar.scss @@ -133,6 +133,26 @@ a.checkbox-only { } } +.doc-toc-side { + position: sticky; + top: 2rem; + font-size: smaller; + + .doc-toc-side-panel { + height: 90vh; + overflow-y: scroll; + } + .toc-level-1 { + margin-top: .5rem; + font-size: 1.2rem; + font-weight: bold; + } + .toc-level-2 { + padding: .1rem 0; + padding-left: 1rem; + } +} + /* * select2 settings for dropdowns on start page */ diff --git a/resources/sass/pages/_apparatus.scss b/resources/sass/pages/_apparatus.scss index a0fc09c2d..935c3cfcc 100644 --- a/resources/sass/pages/_apparatus.scss +++ b/resources/sass/pages/_apparatus.scss @@ -40,6 +40,10 @@ ul.apparatus > li { border-top:1px solid $gray-lighter; padding: 6px 0 6px 12px; margin-bottom:0; + + .apparatusEntry span.hand { + display: none; + } } /* diff --git a/templates/document.html b/templates/document.html index 99c6f57e8..b40ef1669 100644 --- a/templates/document.html +++ b/templates/document.html @@ -53,7 +53,7 @@

CARL MARIA VON WEBER AN
-
+
@@ -71,11 +71,11 @@

-
-

- -

-
- -
-

relatedItems

- -
-
-
-

absouluteChronology

-

prevLetters

- -

nextLetters

- +
+
+

+ +

+
+ +
+

relatedItems

+
-
-
-

korrespondenzstelle

+
+
+

absouluteChronology

prevLetters

nextLetters

+
+
+
+

korrespondenzstelle

+

prevLetters

+ +

nextLetters

+ +
@@ -173,20 +175,45 @@

+
+

+ toc-short +

+
+
+
+
-
+
-
-
+
+ +
-
+

editorial

+
+
+
+

relatedItems

+ +
+
+
+

authors

    @@ -336,4 +363,4 @@

    Proposed citation

-
\ No newline at end of file +
diff --git a/xsl/apparatus.xsl b/xsl/apparatus.xsl index 87afb39e7..e9b31cd5e 100644 --- a/xsl/apparatus.xsl +++ b/xsl/apparatus.xsl @@ -11,6 +11,7 @@ + + + + + + diff --git a/xsl/common_link.xsl b/xsl/common_link.xsl index 3d64aa0ba..382ccd57a 100644 --- a/xsl/common_link.xsl +++ b/xsl/common_link.xsl @@ -40,7 +40,7 @@ - + diff --git a/xsl/sources.xsl b/xsl/sources.xsl new file mode 100644 index 000000000..0430f5055 --- /dev/null +++ b/xsl/sources.xsl @@ -0,0 +1,158 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +