Commit 87709100 authored by Mathias Goebel's avatar Mathias Goebel 🎠
Browse files

Merge branch 'release/2.9.0'

parents 6cb12a45 0fe25bc0
......@@ -4,7 +4,7 @@ local.build.properties
# files generated by ant #
##########################
build
build/
expath-pkg.xml
.DS_STORE
......
image: docker.gitlab.gwdg.de/fontane-notizbuecher/build:latest
variables:
EXIST_DB: "eXist-db-4.3.1"
stages:
- build
- test
- deploy
build-develop:
except:
- master
- tags
stage: build
script:
- ant
artifacts:
paths:
- build/*.xar
build-master:
only:
- master
stage: build
script:
- cp master.build.properties local.build.properties
- ant
artifacts:
paths:
- build/*.xar
installation:
stage: test
script:
- wget --quiet --output-document=${EXIST_DB}.tar.gz https://bintray.com/existdb/releases/download_file?file_path=${EXIST_DB}.tar.gz
- tar -xzf ${EXIST_DB}.tar.gz; mkdir ${EXIST_DB}/lib/test
- ant dependencies
- cp build/*.xar ${EXIST_DB}/autodeploy
- bash ${EXIST_DB}/bin/startup.sh | tee output.log &
# wait for eXist
- while [ $(curl -I -s http://localhost:8080 | grep -c "200 OK") == 0 ]; do sleep 2s; done
# shutdown eXist
- bash ${EXIST_DB}/bin/shutdown.sh
- ls -al /tmp; mv /tmp/tests-* . || true
artifacts:
paths:
- output.log
- tests-*.xml
- ${EXIST_DB}/webapp/WEB-INF/logs/expath-repo.log
upload:
stage: deploy
script:
- FILENAME=$(ls build/*.xar)
- curl -u ci:${EXIST_UPLOAD_PW} -X POST -F file=@${FILENAME} https://ci.de.dariah.eu/exist-upload
project.namespace=http://textgrid.de/ns/SADE
project.version=2.5.5
project.title=Scalable Architecture for Digital Editions
project.abbrev=SADE
project.namespace=http://textgrid.de/ns/SADE-fontane
project.version=2.9.0
project.title=[Fontane] SADE
project.abbrev=SADE-fontane
project.processorversion=4.3.1
<?xml version="1.0" encoding="UTF-8"?>
<project default="xar" name="SADE">
<property environment="env"/>
<property file="local.build.properties"/>
<property file="build.properties"/>
<property name="build.dir" value="build"/>
<xmlproperty file="expath-pkg.xml.tmpl"/>
<target name="xar">
<copy file="expath-pkg.xml.tmpl" tofile="expath-pkg.xml" filtering="true" overwrite="true">
<filterset>
<filter token="project.version" value="${project.version}"/>
<filter token="project.title" value="${project.title}"/>
<filter token="project.abbrev" value="${project.abbrev}"/>
<filter token="project.namespace" value="${project.namespace}"/>
<filter token="project.name" value="${project.name}"/>
<filter token="project.processorversion" value="${project.processorversion}"/>
</filterset>
</copy>
<mkdir dir="${build.dir}"/>
......@@ -19,4 +21,10 @@
excludes="${build.dir}/*"/>
</target>
<target name="dependencies">
<get src="https://ci.de.dariah.eu/exist-repo/find.zip?abbrev=cv&amp;processor=${project.processorversion}" dest="${build.dir}/codeview-latest.xar" verbose="on" ignoreerrors="true"/>
<get src="http://exist-db.org/exist/apps/public-repo/find.zip?abbrev=markdown&amp;processor=${project.processorversion}" dest="${build.dir}/markdown-latest.xar" verbose="on" ignoreerrors="true"/>
<get src="http://exist-db.org/exist/apps/public-repo/find.zip?abbrev=monex&amp;processor=${project.processorversion}" dest="${build.dir}/monex-latest.xar" verbose="on" ignoreerrors="true"/>
</target>
</project>
......@@ -3,7 +3,6 @@ xquery version "3.1";
import module namespace config="http://textgrid.de/ns/SADE/config" at "modules/config/config.xqm";
import module namespace digilib="http://textgrid.info/namespaces/xquery/digilib" at "../textgrid-connect/digilibProxy.xqm";
import module namespace fontaneTransfo="http://fontane-nb.dariah.eu/Transfo" at "modules/fontane/transform.xqm";
import module namespace console="http://exist-db.org/xquery/console";
declare namespace xhtml="http://www.w3.org/1999/xhtml";
......@@ -54,23 +53,40 @@ else if (tokenize($exist:path, '/') = "get") then
let $reqid := request:get-parameter("id", "/xml/data/16b00.xml"),
$id := $reqid => substring-after("/xml/data/") => substring-before(".xml"),
$pagereq := request:get-parameter("page", "1r"),
$page := if( $pagereq = "" ) then "outer_front_cover" else $pagereq,
$alternative := contains($pagereq, "-alt"),
$double := contains($pagereq, "-"),
$page := if( $pagereq = "" )
then "outer_front_cover"
else
if($alternative or $double)
then $pagereq => substring-before("-")
else $pagereq,
$docCollection := $config:projects-dir || $project ||"/data/xml/xhtml/"|| $id ||"/",
$docpath := $docCollection || $page ||".xml",
$doc := doc( $docpath ),
$doc := (doc( $docpath ), if($double) then doc( replace($docpath, $page || "\.xml" , $pagereq => substring-after("-") || ".xml")) else ()),
$error := $doc//error,
$content :=
switch ($exist:resource)
case "code.html" return (
replace(serialize($doc//xhtml:div[@class="teixml"]), "xhtml:", ""),
replace(serialize($doc//xhtml:div[@class="teixml"]), "xhtml:", "")
(: replace the second heading. useful for double-page spread. :)
=> replace("(<b>[\s\S]+?</b>[\s\S]*?)(<b>[\s\S]+?</b>)", "$1"),
serialize($error)
)
case "trans.html" return
replace(serialize($doc/xhtml:body/xhtml:div/xhtml:div[not(@class="teixml")][not(@class="facs")]), "xhtml:", "")
if($alternative)
then serialize($doc/xhtml:body/xhtml:div/xhtml:div[not(@class="teixml")][not(@class="facs")])
=> replace("xhtml:", "") => replace('class="surface"', 'class="surface no-nesting"')
else
serialize($doc/xhtml:body/xhtml:div/xhtml:div[not(@class="teixml")][not(@class="facs")])
=> replace("xhtml:", "")
case "facs.html" return
replace(serialize($doc//xhtml:div[@class="facs"]), "xhtml:", "")
if ($alternative and $id="2128f") (: using one transformation for two renderings :)
then replace(serialize($doc//xhtml:div[@class="facs"]), "xhtml:", "")
=> replace("1671z", "16725")
else
replace(serialize($doc//xhtml:div[@class="facs"]), "xhtml:", "")
case "toc.html" return
replace(serialize(doc( $docCollection || "toc.xml" )), "xhtml:", "")
......
<?xml version="1.0" encoding="UTF-8"?>
<package xmlns="http://expath.org/ns/pkg" name="http://textgrid.de/ns/SADE" abbrev="SADE" version="2.3.2" spec="1.0">
<title>Scalable Architecture for Digital Editions</title>
<dependency package="http://exist-db.org/apps/markdown"/>
<dependency package="http://exist-db.org/apps/monex"/>
</package>
<?xml version="1.0" encoding="UTF-8"?>
<package xmlns="http://expath.org/ns/pkg" name="@project.namespace@" abbrev="@project.abbrev@" version="@project.version@" spec="1.0">
<package xmlns="http://expath.org/ns/pkg"
name="@project.name@"
abbrev="@project.abbrev@"
version="@project.version@"
spec="1.0">
<title>@project.title@</title>
<dependency processor="http://exist-db.org" semver-min="@project.processorversion@"/>
<dependency package="http://exist-db.org/apps/markdown"/>
<dependency package="http://exist-db.org/apps/monex"/>
<dependency package="http://bdn-edition.de/ns/code-view"/>
</package>
project.abbrev=SADE-fontane-master
......@@ -6,7 +6,6 @@ xquery version "3.1";
:)
module namespace config="http://textgrid.de/ns/SADE/config";
import module namespace console="http://exist-db.org/xquery/console" at "java:org.exist.console.xquery.ConsoleModule";
import module namespace config-params="http://exist-db.org/xquery/apps/config-params" at "config.xql";
declare namespace templates="http://exist-db.org/xquery/templates";
......@@ -80,7 +79,7 @@ declare variable $config:project :=
return if($value="") then "textgrid" else $value;
declare variable $config:configDoc := doc( $config-params:projects-dir || $config:project || "/config.xml" );
declare variable $config:configMap := map:new(
for $param in $config:configDoc/config/*[@key]
for $param in $config:configDoc/config/*[./@key]
return map:entry(string($param/@key), string($param))
);
......@@ -96,7 +95,7 @@ return
then $return
else
let $doc := doc( $config-params:projects-dir || $config:project || "/config.xml" )
let $map := map:new(for $param in $doc/config/*[@key] return map:entry(string($param/@key), string($param)))
let $map := map:new(for $param in $doc/config/*[./@key] return map:entry(string($param/@key), string($param)))
return
switch ($key)
case "data-dir" return $config-params:projects-dir || $config:project || "/" || $map($key)
......@@ -144,13 +143,29 @@ declare function config:list-projects() as xs:string+ {
xmldb:get-child-collections($config-params:projects-dir)
};
(:~
: STATUS: UNCLEAR! COMES FROM OLDE SADE! -- Returns the scripts and links
: required by the modules as configured in the project-config either put code
: directly into `<container key="html-head">` or if a module is mentioned in
: the config, its config is checked for <container key="html-head" >
:)
declare function config:html-head($node as node(), $model as map(*)) {
let $head := $model("config")//container[@key='html-head']
return $head/*
declare function local:mkcol-recursive($collection, $components) {
if (exists($components)) then
let $newColl := concat($collection, "/", $components[1])
return
if(xmldb:collection-available($newColl))
then local:mkcol-recursive($newColl, subsequence($components, 2))
else (
xmldb:create-collection($collection, $components[1]),
local:mkcol-recursive($newColl, subsequence($components, 2))
)
else
()
};
(: Helper function to recursively create a collection hierarchy. :)
declare function config:mkcol($path) {
if(not(starts-with($path, "/")))
then error(QName("error", "path"), "Invalid path. Absolute path required.")
else
if($path => matches("[^a-zA-Z0-9\-\.\+/]"))
then error(QName("error", "charset"), "Invalid path. use characters that match [a-zA-Z0-9\-\.\+/] only.")
else
let $components := tokenize($path, "/")[.!=""]
return
local:mkcol-recursive("/" || $components[1], subsequence($components, 2))
};
......@@ -3,7 +3,6 @@ module namespace fsearch = "http://sade/faceted-search" ;
import module namespace kwic="http://exist-db.org/xquery/kwic";
import module namespace config="http://textgrid.de/ns/SADE/config" at "../config/config.xqm";
import module namespace console="http://exist-db.org/xquery/console";
declare namespace tei="http://www.tei-c.org/ns/1.0";
declare namespace bol="http://blumenbach-online.de/blumenbachiana";
......@@ -163,8 +162,6 @@ function fsearch:result-id($node as node(), $model as map(*)) {
};
declare function fsearch:facets($model as map(*), $hits) as map() {
let $test := console:log( $config:configDoc )
return
map:new(
for $facet in $config:configDoc//module[@key="faceted-search"]//facet
return
......
xquery version "3.1";
(:~
: This module provides an API to retrieve index entries as a sequence for a
: given page.
:
: @author Mathias Göbel
: @version 1.0
: @since 2.5.6
: :)
module namespace index="https://fontane-nb.dariah.eu/indexapi";
declare namespace output = "http://www.w3.org/2010/xslt-xquery-serialization";
declare namespace tei="http://www.tei-c.org/ns/1.0";
declare namespace test="http://exist-db.org/xquery/xqsuite";
declare namespace xhtml="http://www.w3.org/1999/xhtml";
import module namespace rest="http://exquery.org/ns/restxq";
import module namespace config="http://textgrid.de/ns/SADE/config" at "../config/config.xqm";
declare variable $index:dataPath := "/db/sade-projects/textgrid/data/xml/data";
(:~
: resolves and lists all references on a given page based on their index data
:
: @param $uri – A valid TextGrid Base-URI without prefix
: @param $surface – a string to match a tei:surface/@n in the document
: (use “-” as delimiter)
: @return a list with all entries
: @see http://localhost:8080/exist/restxq/fontane/index/16b00/62v
: @see https://fontane-nb.dariah.eu/api/index/16b00/62v
: :)
declare
%rest:GET
%rest:path("fontane/index/{$uri}/{$surface}")
%output:method("html")
%test:name("entities per page")
%test:args("16b00", "2v") (: return empty sequence on interleaf :)
%test:assertEmpty
%test:args("", "") (: return custom error INDEX-API1 :)
%test:assertError("INDEX-API1")
%test:args("16b00", "foo") (: return custom error INDEX-API2 :)
%test:assertError("INDEX-API2")
%test:args("16b00", "1r") (: return more then 10 entities :)
%test:assertXPath("count($result//xhtml:li) gt 10")
%test:args("16b00", "2r") (: return 4 groups :)
%test:assertXPath("count($result) eq 4")
function index:entites-per-page($uri as xs:string, $surface as xs:string)
as element(xhtml:ul)* {
let $docpath := $index:dataPath || "/" || $uri || ".xml"
let $surface := tokenize($surface, "-")
(: test for document available :)
return
if(not(doc-available($docpath)))
then
let $docsInDb := collection($index:dataPath)//tei:sourceDoc
/replace(base-uri(), "\.xml|/|db|sade-projects|textgrid|data|xml", "")
=> string-join(", ")
return
error(QName("FONTANE", "INDEX-API1"), "Unable to resolve URI. Try one of " || $docsInDb || "." )
else
let $doc := doc($docpath)
let $page := $doc//tei:surface[@n = $surface]
(: test for surface available :)
return if(not(exists($page)))
then
let $surfacesInDocument := $doc//tei:surface[@n]/string(@n)
=> string-join(", ")
return
error(QName("FONTANE", "INDEX-API2"), "tei:surface not found. Try one of " || $surfacesInDocument || "." )
else
(: test for entries before further processing :)
if(not(exists(($page/tei:zone//tei:rs, $page/tei:surface[not(@n)]//tei:rs)))) then () else
let $entities := ($page/tei:zone//tei:rs/tokenize(@ref, " "), $page/tei:surface[not(@n)]//tei:rs/tokenize(@ref, " ")) => distinct-values()
let $groups := $entities ! substring-before(., ":") => distinct-values()
for $group in $groups
let $translate := local:translate-prefix($group, (count($entities[substring-before(., ":") = $group]) gt 1) )
order by $translate
return
element xhtml:ul {
element xhtml:li {
attribute class {"group", $group},
$translate,
element xhtml:ul {
for $entity in $entities[substring-before(., ":") = $group]
let $ref := substring-after($entity, ":")
let $index := (collection($index:dataPath)/id($ref))[1]
let $name := string($index/*[1])
let $list := local:get-list-by-id($ref)
let $href := "register-" || $list || ".html?e=" || $ref
order by $name
return
element xhtml:li {
attribute data-ref { $entity },
attribute class { $index/local-name() },
element xhtml:a {
attribute href { $href },
attribute target { "_blank" },
$name
}
}
}
}
}
};
(:~
: Translate an index prefix into German.
: @param $prefix a three letter code to resolve
: @param $plural true when plural translation is required
: @response the translation
: :)
declare function local:translate-prefix($prefix as xs:string, $plural as xs:boolean)
as xs:string {
if ($plural)
then
switch ($prefix)
case "eve" return "Ereignisse"
case "psn" return "Personen"
case "plc" return "Orte"
case "org" return "Institutionen"
case "wrk" return "Werke"
default return "The prefix " || $prefix || " is not in the dictonary."
else
switch ($prefix)
case "eve" return "Ereignis"
case "psn" return "Person"
case "plc" return "Ort"
case "org" return "Institution"
case "wrk" return "Werk"
default return "The prefix " || $prefix || " is not in the dictonary."
};
declare
%test:name("entity list relation")
%test:args("Dom_Karlos_Figur") (: person in wrk :)
%test:assertEquals("list-works")
%test:args("Purschian") (: person :)
%test:assertEquals("listPerson")
function local:get-list-by-id($id as xs:string)
as xs:string {
let $entity := collection($index:dataPath)/id($id)
let $test := if($entity[2]) then error(QName("FONTANE", "INDEX-API3"), "Entity »" || $id || "« has more then one occurence." ) else ()
return
switch ( $entity/local-name() )
case "event" return "listEvent"
case "org" return "listOrg"
case "place" return "listPlace"
case "person" return
if($entity/ancestor::tei:item)
then local:get-list-by-id( ($entity/ancestor::tei:item)[last()]/string(@xml:id) )
else "listPerson"
case "personGrp" return
if($entity/ancestor::tei:item)
then local:get-list-by-id( ($entity/ancestor::tei:item)[last()]/string(@xml:id) )
else "listPerson"
default return
let $list := ($entity/ancestor::tei:list[@type])[last()]
return
$list/local-name() || "-" || string($list/@type)
};
declare
%rest:GET
%rest:path("fontane/index/entity/{$id}")
%output:method("html")
function index:rendered-entity($id as xs:string)
as element(xhtml:li)? {
doc("/db/sade-projects/textgrid/data/xml/xhtml/index.xml")//xhtml:li[@id = $id]
};
xquery version "3.1";
(:~
: This module prepares the index html.
: @author Mathias Göbel
: @version 1.0
: @see https://fontane-nb.dariah.eu/register.html
:)
module namespace f-indexviewer="http://fontane-nb.dariah.eu/indexviewer";
import module namespace f-indexproc="http://fontane-nb.dariah.eu/indexproc" at "index-processor.xqm";
import module namespace config="http://textgrid.de/ns/SADE/config" at "../config/config.xqm";
declare namespace ore="http://www.openarchives.org/ore/terms/";
declare namespace rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#";
declare namespace tei="http://www.tei-c.org/ns/1.0";
declare namespace test="http://exist-db.org/xquery/xqsuite";
declare namespace xhtml="http://www.w3.org/1999/xhtml";
declare
%test:setUp
function f-indexviewer:setup() {
if( xmldb:collection-available("/db/sade-projects/textgrid") )
then true()
else
(: read test config :)
let $testconfig := doc("tests.xml")//testdata[@module="f-indexviewer"]
(: prepare the collections :)
let $prepare-collections :=
for $create in $testconfig//create/collection
return
xmldb:create-collection($create/@target, $create/@new)
(: prepare documents :)
let $prepare-documents :=
for $create in $testconfig//create/document
return
xmldb:store($create/@collection, $create/@name, $create/*)
let $prepare-documents-from-template :=
for $create in $testconfig//create/document-template
let $template := $create/template/*
return
for $data in $create//data
let $doc := doc( xmldb:store($create/@collection, $data/@name, $template) )
return
update insert $data/* into $doc//tei:body
return true()
};
declare
%test:tearDown
function f-indexviewer:teardown(){
xmldb:remove("/db/sade-projects")
};
(: Main cache function
: @return path to the cached document :)
declare
%test:name("cache")
%test:assertTrue
(: %test:pending (: throws NPE on non-initialized db. needs some data from the grid. :):)
function local:cache()
{
let $set-option := util:declare-option("exist:output-size-limit", "2000000")
let $collection-uri := "/db/sade-projects/textgrid/data/xml/xhtml",
$resource := "index.xml"
let $agg := '253st.xml' (: TextGrid Aggregation containing all index files :)
let $uris := (doc('/db/sade-projects/textgrid/data/xml/agg/' || $agg)
//ore:aggregates/substring-after(@rdf:resource, 'textgrid:')
)[. != "25547"] (: omit the bibliography here :)
let $lastMod := $uris ! xmldb:last-modified($f-indexproc:dataPath, . || '.xml')
return
if(not(local:login($collection-uri)))
then error(QName("FONTANE", "INDEXVIEW1"), "unable to authenticate.")
else
if( xmldb:last-modified($collection-uri, $resource) gt max($lastMod) )
then
(: prerendered index younger than index files: do nothing :)
$collection-uri || "/" || $resource
else
(: create the cache :)
xmldb:store($collection-uri, $resource, <xhtml:div>{util:eval('f-indexproc:register()')}</xhtml:div>)
};
(: forces the creation of a new cache file
: @return document-node() of the index cache file :)
declare function f-indexviewer:prepare-new-cache()
as document-node() {
let $path := "/db/sade-projects/textgrid/data/xml/xhtml/index.xml"
let $cleanup :=
if( doc-available($path) )
then xmldb:remove("/db/sade-projects/textgrid/data/xml/xhtml", "index.xml")
else true()
return
doc( local:cache() )
};
(:~
: Recursive transformation of the index document, if a specific item is requested.
: @param $nodes – node to be parsed
: @param $id – a single id prepared with generate-id()
: :)
declare function local:transform-entity($nodes as node()+, $id as xs:string)
as node()* {
for $node in $nodes
let $thisId := generate-id($node)
return
if ($thisId = $id)
then
(: set 'active' class :)
element { node-name($node) } {
$node/@*[local-name() != "class"],
attribute class {
string($node/@class),
"fhighlighted"
},
local:transform-entity($node/node(), $id)
}
else if(starts-with($id, $thisId))
then
typeswitch ($node)
case element(*) return
element { node-name($node) } {
if(contains($node/@class, "tab-pane"))
then
($node/@*[local-name() != "class"],
attribute class {
string($node/@class),
"active"
})
else
$node/@*,
local:transform-entity($node/node(), $id)
}
default return
$node
else $node
};
declare function f-indexviewer:main($model as map()*, $node as node(), $index as xs:string) {
if ($f-indexproc:notebookParam)
then
f-indexproc:register($index)[./@id = $index]
(: xhtml prefixes w/o xmlns attr in the output. work around with: :)
=> serialize() => parse-xml()
else
let $doc := doc( local:cache() )
return
if ($f-indexproc:getEntity)
then
let $id := generate-id($doc//xhtml:li[@id = $f-indexproc:getEntity])
return
local:transform-entity($doc/xhtml:div/xhtml:div[@id = $index], $id)
else
$doc/*/xhtml:div[@id = $index]
};
declare function f-indexviewer:tabs($nodes as node(), $model as map(*), $index as xs:string) {
local:transfrom-tabs($nodes/*, $index)
};
(:~
: Recursive transformation of a given node from the template to a
: represent a list of tabs with current index view marked `active`.
: @param $nodes – nodes to transform
: @param $index – the index that should be marked `active`
: :)
declare
%test:name("mark active tab")
%test:arg("nodes", "<li xmlns=""http://www.w3.org/1999/xhtml""><a href=""register-listEvent.html"">Ereignisse</a></li>")
%test:arg("index", "listEvent")
%test:assertXPath("$result/@class = 'active'")
%test:arg("nodes", "<div xmlns=""http://www.w3.org/1999/xhtml""/>")
%test:arg("index", "listEvent")
%test:assertEmpty
function local:transfrom-tabs($nodes as element()+, $index as xs:string) {
for $node in $nodes
return
typeswitch ( $node )
case element(xhtml:div) return
$node/node() ! local:transfrom-tabs(., $index)
case element(xhtml:ul) return