diff --git a/README.md b/README.md
index f9f8f5b5..a09379b8 100644
--- a/README.md
+++ b/README.md
@@ -4,6 +4,19 @@ An extensible framework for digital Editions for the [eXist XML database](https:
This framework still lacks a good name. If you have an idea, please let me know!
+## Incompatible changes
+
+Release 24Q1 dropped support for METS-based projects. As METS files can have a number of very different ways of encoding
+information, especially when it comes to behaviours, native support is hard to achieve. At the same time, most
+installations use wdb+’s native wdbmeta system as this is what the admin functions work with.
+If you require METS support, please open an issue and provide an example of your METS files. We will then try to create
+import and export functions.
+
+Release 24Q1 introduced changes to the transformation: previously, XIncludes were not expanded before the XSLT was
+applied to a file. This has now been dropped meaning that XIncludes will always be expanded. This is most likely the
+expected behaviour. If you want to ignore XInclude, you can add this as a global setting in eXist: in
+`${eXist-dir}/etc/conf.xml` set `serializer/@enable-xinclude` to `no`.
+
## Installation
You need a working instance of eXist (4.0 or later). It is recommended that you use the default software selection
during installation. The default memory settings usually work very well but you can, of course, always give eXist a
@@ -12,38 +25,10 @@ little more RAM.
1. Clone this repo including its submodules (xstring, wdbmeta)
1. `cd edoc`
1. run `ant`
-1. install the `.xar` file created in `edoc/build/` using eXist's dashboard
+1. install the `.xar` file created in `edoc/build/` using eXist's dashboard or (https://github.com/eXist-db/xst)[XST]
The app will be installed into `/db/apps/edoc`.
-### eXgit
-Additionally, it is possible to use [eXgit](https://github.com/dariok/exgit) to clone the current version directly into a running eXist instance.
-
-1. Install eXgit as stated in the repo.
-1. create a user `wdb` and a group `wdbusers` for the framework and log in under that name –– CAVEAT: this user, at least for the duration of the installation, **needs to be** in the **dba** group!
-1. create the target collection (default would be `/db/apps/edoc`) as this user
-1. open eXide from eXist's Dashboard
-1. paste:
- ```
- xquery version "3.1";
-
- import module namespace exgit="http://exist-db.org/xquery/exgit" at "java:org.exist.xquery.modules.exgit.Exgit";
-
- let $whereToClone := "/home/user/git/wdbplus"
- let $targetCollection := "/db/apps/edoc"
-
- let $cl := exgit:clone("https://github.com/dariok/wdbplus", $whereToClone)
- let $ie := exgit:import($whereToClone || "/edoc", $targetCollection)
- let $ic := exgit:import($whereToClone || "/edoc/config", "/db/system/config/db/apps")
- ```
-1. replace the value of `$whereToClone` with the full target directory on your file system where the app shall be cloned into
-1. if you do not want to install into `/db/apps/edoc`, change the value of `$targetCollection` to the full DB path
-1. run the script
-1. open `post-install.xql` in your target collection
-1. if you did not install into `/db/apps/edoc`, change `$targetCollection` accordingly
-1. run `post-install.xql` to set rights and index configuration
-
-
### manual installation
1. clone this repo including its submodules
1. put folder `edoc` anywhere you want in your eXist; the default would be `/db/apps/edoc`; you can also rename it to your needs (in this case, you have to adjust the paths in the next steps!).
@@ -55,7 +40,14 @@ Set the name for the instance and other settings in `edoc/config.xml` or using t
## Creating and uploading projects
While many different ways of putting data into the application are possible, the standard way is to have one collection
-under data for each project. It is possible to create an initial setup using `admin/admin.html`. The following describes a manual installation and assumes that you work with a standard setup, i.e. have installed the app
+under data for each project.
+
+### Using admin functions
+It is possible to create an initial setup using `admin/admin.html`. After creating a project, you can immediately start
+uploading files using the upload form. wdb+ will take care of creating meta data entries.
+
+### Manual approach
+The following describes a manual installation and assumes that you work with a standard setup, i.e. have installed the app
into `/db/apps/edoc` and want to put your projects into `/db/apps/edoc/data/yourproject`.
1. create `wdbmeta.xml` in `/db/apps/edoc/data/yourproject`, either by copying, pasting and editing the example below or by using
@@ -102,6 +94,7 @@ See the Wiki for details!
* Repertotium frühneuzeitlicher Rechtsquellen
* Protokolle der Sitzungen der Gesamtakadmie
* Akademie der Wissenschaften, Heidelberg
- * Theologenbriefwechsel
+ * Theologenbriefwechsel
+* ULB Darmstadt
If you use wdbplus for your editions, please drop me a message so I can add you to this list.
diff --git a/doc/Basic-collection-structure.md b/doc/Basic-collection-structure.md
deleted file mode 100644
index 63fa11b0..00000000
--- a/doc/Basic-collection-structure.md
+++ /dev/null
@@ -1,80 +0,0 @@
-## Intro
-
-While the app was built with the possibility in mind to adapt it to different local needs and data structures, there is a default structure. While the app tries hard to figure out the correct structure by itself, this may fail. If you use a structure different from the default, you may need to adapt several scripts and keep that in mind when updating and upgrading.
-
-## Default Structure
-
-The default setup install the app into the collection `/db/apps/edoc` of eXist. It contains the [[main HTML files|main-html-files]] and the everything else the app needs to run. It is also home to several subcollections:
-
- edoc
- ├─admin
- ├─data
- ├─global
- ├─include
- ├─modules
- ├─resources
- ├─rest
- ├─schema
- ├─templates
- ├─(annotations)
- ├─(doc)
-
-* `admin`, as the name suggests, contains a few scripts to help admins keep an overview of the projects within this installation (more are to be added in later versions).
-* `data` is where the different projects go as subcollections. While it can be empty, it may contain [[start.xml|main-files#start]] and should contain [[wdbmeta.xml]] to give a global start page or set global metadata.
-* `global` is where globally available or root level content is stored, e.g. `index.html`. **This is the only place in the app root where users should (and need to) make changes**
-* `include` contains recent versions of related projects, namely the schema for [[wdbmeta.xml|main-files#wdbmeta]] and a collection of XSL/XQuery functions to deal with strings (extending the normal XPath string functions).
-* `modules` is where the main global scripts go.
-* `resources` contains global resources such as default XSLTs, global CSS and JavaScript.
-* `rest` contains scripts for the RESTful interface. While it is possible for users to change these scripts, it is recommended to instead add scripts instead of changing existing ones.
-* `schema` contains schema files for global files other than `wdbmeta.xml` (currently, this is only `config.xml`).
-* `templates` contains the rump HTML files used for the templating system. While it is possible to change these files, most changes can better be done by using [[project specific layout and functions|project-specifics]]. The standard files here may be overwritten by an update.
-* `annotation` and `doc` are not in use yet but are to be considered 'reserved' as they will be used for internal functions in upcoming releases.
-
-Except for `global`, there are no user servicable parts in these collections. All changes may be overwritten by an update or upgrade. Instead, use the [[configuration options|global-configuration]] and [[project specific layout and functions|project-specifics]] to adapt functions and layout to your needs.
-Should you really require a change in one of these subcollections, consider opening an issue instead so this can be changed to an option that can be set on a project or instance level.
-
-## Non-default structures
-
-### projects as subcollections of `edoc`
-It is possible to deviate from the general structure. For instance, one might want to forego the `data` subcollection and store all projects as a subcollection within `edoc` itself. This is possible and should be recognized correctly by all scripts; however, as the main call to view a page is via `view.html` and an ID, this is not strictly necessary. Should you need it e.g. to maintain a stable URL for the source XML/XSLT/etc. files, consider using a reverse proxy instead, especially if you run into problems reading and displaying files.
-
-### different name than `edoc`
-It is also possible to name the collection other than `edoc`. In fact, this feature will be put to use in a later release as part of the possibility to have both _publication_ and _workbench_ [[roles|server-roles]] run on the same eXist server. All scripts should be able to figure out the correct name.
-
-### as a subcollection of `db` instead of `/db/apps`
-This is possible, too, and should not require additional changes. If you run into problems with the URLs generated by the scripts, automatic resolution of the basic URL might have failed. Consider setting the appropriate option in [[config.xml|global-configuration]]
-
-### port 80 and/or no mention of 'exist' in URL
-If you want to have a URL without port 8080 and the 'exist' part, so 'http://example.com/edoc/view.html' rather than 'http://example.com:8080/exist/apps/edoc', you need to adjust eXist's configuration. Depending on the way you deployed eXist, the port configuration can be found e.g. in the Jetty config files (e.g. `tools/jetty/etc/jetty-http.xml`). In eXist's main `controller-config.xml` change
-
-
-
-to
-
-
-
-
-and in `exist-webapp-context.xml`, change
-
- /exist
-
-to
-
- /
-
-If you cannot access the collection or any of the builtin apps, e.g. Dashboard or monex, the “portal” might be blocking Jetty’s `/`-context. Try editing `tools/jetty/webapps/portal/WEB-INF/jetty-web.xml` and change the context to something different than `/` or `/exist`, e.g. `/portal`.
-Most likely, Dashboard etc. will not be immediately accessible after the splash screen (which, on a production server, should not be a problem) but need to be accessed manually under `$server/apps/dashboard/index.html`.
-(see https://sourceforge.net/p/exist/mailman/message/35823429/)
-
-Another way of doing this – and maybe a better one if this is available to you – is to use a reverse proxy to point to `exist/apps/edoc`. Depending on your setup, you may lose access to eXide or monex. To solve this, add the following to your `controller.xql` before any redirect that checks for `html`:
-
-
-
-
-
-
-
-and alike for monex.
-
-### data collection other than `data`
-No problems are expected here as the scripts should be able to figure out the correct paths. As with all the other cases, please report any issues you may find.
\ No newline at end of file
diff --git a/doc/CSS-files-and-classes.md b/doc/CSS-files-and-classes.md
deleted file mode 100644
index 0fb27ec1..00000000
--- a/doc/CSS-files-and-classes.md
+++ /dev/null
@@ -1,48 +0,0 @@
-## global CSS files
-
-All these files define global CSS rules. While it is possible to change them
-directly, the preferred way to go is via
-[[project specific files|project-specifics]] as these global files may be
-replaced during an update or upgrade.
-
-|file|rules|
-|--|--|
-|resources/css/wdb.css|basic layout of any page – this one is loaded first by all pages in the templating system|
-|resources/css/function.css| basic layout for function pages (small aside left, wide main right)|
-|[[resources/css/view.css\|css-files-and-classes#viewcss]]| main layout file for _header_, _nav_, _main_ and _aside_ in of view.html|
-|resources/css/search.css|additional layout for search page and results|
-|[[resources/css/start.css\|css-files-and-classes#startcss]]| additional layout for `start.html`|
-|[[resources/css/footnotes.css\|css-files-and-classes#footnotescss]]| additional layout for footnotes|
-
-## overview of classes
-### view.css
-|class / rule / id|intended for|
-|--|--|
-|header|the horizontal header at the top|
-|main|main text area to the left|
-|nav|(global) navigation|
-|#wdbRight|the right hand side|
-|#fac|container for facsimile (on the right)|
-|#facsimile|iframe to load facsimiles|
-|#wdbShowHide|central vertical bar to adjust size|
-|#wdbContent|container for text in _main_|
-|footer|the footer below a text (container)|
-|span.dispOpts|options in the header (usually to the right)|
-|#marginalia_container|container for marginalia|
-
-### footnotes.css
-|class / rule / id|intended for|
-|--|--|
-|div.footnotes|container for all footnotes|
-|#kritApp, #FußnotenApparat, #critApp, #apparatus|one group of notes|
-|hr.fnRule|footnote rule (above)|
-|a.fn_number|footnotes's identifier in the main text|
-|.fn_number_app|footnotes's identifier within the footnote|
-|span.footnoteText|footnote's text (usually after the identifier)|
-
-
-### start.css
-|class / rule / id|intended for|
-|--|--|
-|#toc_title|title for the table of contents|
-|div.startImage|an image to be displayed on the right|
\ No newline at end of file
diff --git a/doc/Global-Configuration.md b/doc/Global-Configuration.md
deleted file mode 100644
index d76b4aae..00000000
--- a/doc/Global-Configuration.md
+++ /dev/null
@@ -1,35 +0,0 @@
-# Global Configuration
-
-All global configuration options, i.e. those that affect how the app works, are set in `$approot/config.xml`.
-If you use the [[default setup|basic-collection-structure#default-structure]], `$approot := /db/apps/edoc`.
-
-## Settings in `config.xml`
-### meta
-- `name` – a long title for this instance of the app
-- `short` – a short title, e.g. to be used in `html:title`
-
-### role
-- `type` – the [[role|server-roles]] of this instance
-- `peer` – for a _workbench_, this points to the House of Lords, i.e. the _publication_ instance
-
-See the documentation of the [[server roles|server-roles]] for more detail.
-
-### params
-- `param` – a key-value pair for global parameters that are available in all scripts and will be passed on to the model.
-
-Not really implemented yet but planned for version 2.0.
-
-### server
-A full URL, reachable from the outside, to be used if the automatic resolution in `app.xql` does not work or needs to be overwritten. This needs to point to the collection containg `config.xml` (thus, the standard setting would be `http://yourexist.tld/exist/apps/edoc/`)– a setting here overwrites the automatic processing and will be globally available as `$wdb:edocBaseURL`, the server's name (or IP) as `$wdb:server`.
-While all standard scripts should be able to figure this out correctly, certain setups may cause problems.
-
-Scripts invoked via RESTXQ will not be able to use automatic resolution – if you need the base URL from within a RESTXQ endpoint (e.g. for the IIIF image descriptor), you MUST set this option.
-
-### rest
-A full URL which is the base for REST calls. This will be used by JavaScript functions, e.g. to load navigation or to insert/retrieve annotations. This must be set if the rest endpoint is not available under the usual location (i.e. `http://yourexist.tld/exist/restxq/edoc/` for the standard setup). This might be the case if you hid parts of the standard path by eXist's configuration or reverse proxying.
-
-NB: this needs to include the “edoc/” part
-
-## Projects
-In order to create a project, you have to create a collection for it and make the most important settings in `wdbmeta.xml`. The initial settings can be done using `admin/admin.html` (New Project).
-After that, you have to add at least one view and an entry for every file you want to access.
\ No newline at end of file
diff --git a/doc/Global-variables.md b/doc/Global-variables.md
deleted file mode 100644
index 364552f1..00000000
--- a/doc/Global-variables.md
+++ /dev/null
@@ -1,35 +0,0 @@
-# Global variables
-## $model
-
-In several instances, most prominently in `app.xqm`, a parameter called `$model` is passed to functions.
-This is part of eXist's templating system and has been used in several locations to allow for uniform distribution of common parameters.
-
-`$model` always is a `map(*)`. The most important parameters MUST be the same in all instances. This means:
-
-| parameter | contents |
-|--|--|
-| `ed` | the ID of the Collection (= `@xml:id` of `meta:projectMD` or `mets:mets`) |
-| `fileLoc` | full path to the current Resource |
-| `id` | a file's ID (e.g. file to be displayed) |
-| `infoFileLoc` | full path to `wdbmeta.xml` or `mets.xml` |
-| `pathToEd` | the full DB-Path to the Collection (= `substring-before($infoFileLoc, '/wdbmeta.xml')`) |
-| `projectFile` | path to Project’s `project.xqm`|
-| `projectResources` | path to Project’s resource folder (= `substring-before($projectFile, 'project.xqm') || 'resources'`)|
-| `title` | the title of the file or project |
-| `view` (app.xqm only) | the `view` query parameter as pass in the call to `view.html` |
-| `xslt` (app.xqm only) | full path to the XSLT to be used for transformation |
-| `p` (function.xml only) | all values from `p` query parameter parsed into a `map(*)` |
-
-
-## parameters in `wdb` namespace
-The [[wdb namespace|list-of-namespaces]] contains several global parameters that can be accessed from every script that imports `app.xql`:
-
-|name|contents|
-|--|--|
-|`$wdb:edocBaseDB`| same as `$config:root` – the path to where the application is installed within `/db/`.|
-|`$wdb:configFile`| the (parsed) config file (`{$wdb:edocBaseDB}/config.xml`).|
-|`wdb:data`| the path to the data collection. It is assumed that this is the top collection with a `wdbmeta.xml` file.|
-|`wdb:server`| the server's address including protocol and port – if automatic resolution does not work, set it manually in [[config.xml\|global-configuration]].|
-|`$wdb:edocBaseURL`| the full URL to the app's root or the current subcollection.|
-|`$wdb:role`| the [[role\|server-roles]] of this instance.|
-|`$wdb:peer`| this instance's peer, if it is a workbench.|
diff --git a/doc/Home.md b/doc/Home.md
deleted file mode 100644
index c668592f..00000000
--- a/doc/Home.md
+++ /dev/null
@@ -1,15 +0,0 @@
-Welcome to the wdbplus wiki!
-
-To get started, please refer to the information in `project.md`.
-
-Some basic concepts etc. are to be documented here. Until there is a more definite documentation included within the app itself, this is the place for doc to go. It may also serve as a stable target for documentation of older releases.
-
-Your point of entry should be [[global-configuration]] which introduces you to the most important settings and caveats.
-
-If you want to know more about the structure of collections within the app and what you can change, please have a look at [[Basic Collection Structure|basic-collection-structure]]. This page also contains information about settings to change when you want to use a different setup, e.g. place the app outside of `/db/apps`.
-
-An overview of how projects can be customized and the app's configuration options, see [[project-specifics]] as well as [[wdbmeta.xml]] for project metadata.
-
-Functions you can use are listed in [[the list of JavaScript functions|js-functions]] and [[the list of XQuery functions|xq-functions]].
-
-To learn about what the most important files in this app do, consult [[the list of main HTML files|main-html-files]] and [[the list of other main files|main-files]].
\ No newline at end of file
diff --git a/doc/Include-an-image-viewer-via-projectSpecifics.md b/doc/Include-an-image-viewer-via-projectSpecifics.md
deleted file mode 100644
index 39da0500..00000000
--- a/doc/Include-an-image-viewer-via-projectSpecifics.md
+++ /dev/null
@@ -1,68 +0,0 @@
-As an example how to use projectSpecifics and as a how-to for embedding a viewer, we will have a look at how to include the OpenSeaDragon viewer in your project or instance.
-
-1. Images are usually displayed to the right. So we need to include the viewer in the right part of `view.html`, which is the element `aside` (on the basic page layout cf. [[main-html-files]]). To include the necessary files, we will create a footer here. A globally defined footer will live in `edoc/resource/rightFooter.html` while a project specific footer will be located in `edoc/data/yourProject/resource/projectRightFooter.html` or defined by a function `wdbPF:getProjectRightFooter`.
-1. Create a JS file `osdviewer.js` for all functions necessary for the viewer in `edoc/resource` or ``edoc/data/yourProject/resource`:
-
- $.holdReady(true);
- var viewer = OpenSeadragon({
- preserveViewport: true,
- visibilityRatio: 1,
- minZoomLevel: 1,
- defaultZoomLevel: 1,
- id: "fac",
- sequenceMode: true,
- tileSources: []
- });
-
- id = $("meta[name='id']").attr("content");
- rest = $("meta[name='rest']").attr("content");
- $.get(rest + "resource/iiif/" + id + "/images", function(data){viewer.open(data);});
-
- viewer.addHandler('page', function(source, page, data){
- $('#pag' + (source.page + 1))[0].scrollIntoView();
- });
- viewer.addHandler('open', function() { $.holdReady(false); });
-
-1. In this example, we create the HTML file with only one line:
-
-
-
- Adjust the path in `@src` to point to where you stored the JS in the step before.
-1. In a project’s `project.xqm` (or the global `project.xqm` for those projects without their own), load the main OpenSeadragon JS. Change `wdbPF:getProjectFiles` so it looks similar to this (of course you should keep `link` or `script` elements you already added):
-
- declare function wdbPF:getProjectFiles ( $model as map(*) ) as node()* {
- (
- ,
- ,
-
- )
- };
-
-1. In your `project.js` overwrite `displayImage()` so that it sends the sequence number of the page to be displayed to OpenSeadragon, e.g.
-
- function displayImage(element) {
- let pbs = $('body').find('.pagebreak a');
- let pos = pbs.index(element);
- viewer.goToPage(pos);
- }
-
-1. `osdviewer.js` created above makes use of the IIIF image descriptor endpoint of wdb+. For it to work, your TEI files need to have basic information about the images in a `facsimile` element, e.g.:
-
-
-
-
-
-
-
- This assumes that you have your images stored on a IIIF server. If that is the case, you should be done. If not, please read on.
-1. If you do not have your images stored on a IIIF server, you can still specify images by URL as tile source(s). Let’s assume the image URLs are contained in an HTML `.pagebreak a`, attribute `@href`. In `osdviewer.js` from step 2 above, replace the line starting with `$.get` with
-
- let tiles = [];
- $('.pagebreak a').each(function(){
- let img = {
- type: 'image',
- url: $(this).attr('href')
- };
- tiles.push(img);
- });
- viewer.open(tiles);
\ No newline at end of file
diff --git a/doc/JS-functions.md b/doc/JS-functions.md
deleted file mode 100644
index c9266b87..00000000
--- a/doc/JS-functions.md
+++ /dev/null
@@ -1,36 +0,0 @@
-## Files declaring JavaScript functions
-
-| file | used for |
-|--|--|
-| resources/scripts/admin.js | in admin functions|
-| resources/scripts/annotate.js| user annotations in texts|
-| resources/scripts/function.js| main functionality|
-
-## functions declared for common use
-
-### annotate.js
-|function|use|
-|--|--|
-|anno()|prompt for simple annotation text and forward text and IDs to `insert.xql`|
-|$(document).ready()|load annotations from `return.xql`|
-
-### function.js
-|function|use|
-|--|--|
-|$(document).ready()| evaluate **&l=from-to** and highlight elements with ID from, to and all in between|
-|loadTargetImage()| load the image for the page where #target is located – calls _displayImage(href)_|
-|marginPos(), positionMarginalia (index, element)| position marginalia within a `div class="#marginalia_container`|
-|getPosition(el)| get the (absolute) vertical position of _el_|
-|mouseIn(event)| load a note into _#ann_ – contains legacy code for hovering boxes|
-|mouseOut(event)| remove legacy hovering box after timeout|
-|show_annotation(dir, xml, xsl, ref, height, width)| show info from `entity.html` in _#ann_|
-|clear(id)|close _#id_ or all info displayed in _#ann_|
-|commonAncestor(e1, e2)|find the common ancestor for _#e1_ and _#e2_|
-|sprung(event)|highlight a section defined by 'targ' und 'targe'|
-|highlightAll(startMarker, endMarker, color, alt)|highligh _#startMarker_, _#endMarker_, and all elements in between with $color and optionally display $alt as text|
-|toggleNavigation()|display/hide _#nav_|
-|getUniqueId()|return an ID that is unique at runtime|
-|doLogout()|log out|
-|displayImage(href)|actually display href in _#facsimile_|
-|toggleRightside()|adjust width of _#wdbContent_ to 75% or back to 50%|
-|close()|hide the facsimile|
\ No newline at end of file
diff --git a/doc/List-of-namespaces.md b/doc/List-of-namespaces.md
deleted file mode 100644
index 88ad6ca3..00000000
--- a/doc/List-of-namespaces.md
+++ /dev/null
@@ -1,18 +0,0 @@
-# List of namespaces used in the app
-
-| Prefix| Namespace URI| file|user|
-|--|--|--|--|
-|wdb| https://github.com/dariok/wdbplus/wdb | `modules/app.xql`| |
-|wdba|https://github.com/dariok/wdbplus/auth | `modules/auth.xqm`| |
-|wdbe|https://github.com/dariok/wdbplus/entity | `modules/entity.xqm`| |
-|wdbErr|https://github.com/dariok/wdbplus/errors | `modules/error.xqm`|(*)|
-|wdbm|https://github.com/dariok/wdbplus/nav | `modules/nav.xqm`| |
-|wdbpq|https://github.com/dariok/wdbplus/pquery | `modules/pquery.xqm`|* |
-|wdbq|https://github.com/dariok/wdbplus/wdbq | (project specific xql)|* |
-|wdbSearch|https://github.com/dariok/wdbplus/wdbs | `modules/search.xqm`| |
-|wdbs|https://github.com/dariok/wdbplus/stats | `modules/stats.xqm`| |
-|wdbPF|https://github.com/dariok/wdbplus/projectFiles | `{$projectDir}/project.xqm`|* |
-|wdbRc|https://github.com/dariok/wdbplus/RestCollections | `rest/rest-coll.xql`| |
-|wdbRf|https://github.com/dariok/wdbplus/RestFiles | `rest/rest-files.xql`| |
-
-Namespaces that have an asterisk in the “user” column are to be extended for [[project specifics|project-specifics]].
\ No newline at end of file
diff --git a/doc/Main-HTML-files.md b/doc/Main-HTML-files.md
deleted file mode 100644
index 208b83a8..00000000
--- a/doc/Main-HTML-files.md
+++ /dev/null
@@ -1,47 +0,0 @@
-# Main HTML files
-
-## files in `$approot`
-
-### entity.html
-This file will be included via AJAX if additional information for an “entity” is to be displayed.
-Here, entity is to be understood as ”POKb” (German: _Personen, Orte, Körperschaften, bibliographische Angaben_ – “persons, places, organizations, bibliographic data”) for which additional information is supplied from an index file or external source.
-
-_Template:_ `page2.html`
-
-### index.html
-Serves as the main point of entry by displaying an inventory of all projects currently present in the instance. It is assumed, that every project uses a `wdbmeta.xml` and that every `wdbmeta.xml` describes a project. Thus, subprojects are recognized.
-Projects that solely rely on a `mets.xml` will be recognized and displayed, too. Subporjects for a METS-project are not supported, though.
-
-_Template:_ `page2.html`
-
-### query.html
-A wrapper page for XQuery scripts that should display their input or result via the templating system. See [[the page on project specific setting||project-specifics#queries]] for more detail on how to use this.
-
-_Template:_ `function.html`
-
-### search.html
-Does roughly the same as query.html but is made especially for search pages. It wraps input/output for full text searches and includes some help.
-
-_Template:_ `function.html`
-
-### start.html
-This file is to be called with an ID parameter pointing to the project: `{$edocBaseURL}/start.html?id=projectID`. It
- will display a start page for that project. By default, this will be the navigation as defined by `wdbmeta.xml` on the
- left and a generic title page on the right. For more information on how to customize the rendering of `start.html`,
- see [[start.html]].
-
-_Template:_ `function.html`
-
-### view.html
-The main entry point to display an HTML representation of an XML file in any project.
-
-_Template:_ `layout.html`
-
-## Description of basic layout
-### `layout.html`
-- 100% width `header` (fixed)
-- below at initially 50% width each `main` (left), `aside` (right)
-- `main` and `aside` may contain a (globally defined or project specific) footer
-### `function.html`
-- 100% width `header` (fixed)
-- below `aside` (left) 30% width, `main` (right) 70% width
\ No newline at end of file
diff --git a/doc/Main-files.md b/doc/Main-files.md
deleted file mode 100644
index 03201da0..00000000
--- a/doc/Main-files.md
+++ /dev/null
@@ -1,18 +0,0 @@
-# Main files
-
-This list the main (non-HTML-)files that you should know about.
-These are usually meant to be adapted to your needs and play a special role for customization.
-
-## `project.css` and `project.js`
-See [[project specifics|project-specifics]] for information about how to use these files.
-
-## wdbmeta.xml
-This is the central information file for your project.
-It was developed from the METS standard and is (planned to be) transformable into a standard `mets.xml`.
-However, the focus was on easy editing, high flexibility and the possibility to automatically enter new files.
-The schema with basic documentation of this file is available under `{$approot}/includes/wdbmeta`.
-A more detailed discussion of the options and the file's processing can be found under [[wdbmeta.xml]].
-
-## project.xqm
-This files contains several XQuery functions you can use to load [[project specific layout and functions|project-specifics]], define information for the HTML-header etc.
-A more detailed discussion of this file is available under [[project.xqm]].
\ No newline at end of file
diff --git a/doc/Naming,-finding,-and-identifying-projects-and-files.md b/doc/Naming,-finding,-and-identifying-projects-and-files.md
deleted file mode 100644
index 279fe03c..00000000
--- a/doc/Naming,-finding,-and-identifying-projects-and-files.md
+++ /dev/null
@@ -1,22 +0,0 @@
-## Project
-A **project** is any set of collections (i. e. editions) “held together“ by a shared `project.xqm`. In terms of database
-structure, all elements of this set MUST be subcollections of the collection holding the common `project.xqm`. This
-`project.xqm` is shared by all children (but may be overwritten); a project SHOULD have a `wdbmeta.xml` of it own.
-
-## Collection
-A **Collection** (usually one edition or one phase phase of a longer project) is always identified by its
-[[wdbmeta.xml]]. A Collection always lives in an eXist-collection of its own. It may have children: these need to live
-in an eXist sub-collection and MUST have a `wdbmeta.xml` of their own. It is also possible to have further eXist
-sub-collections without `wdbmeta.xml` to bring order to the chaos of larger projects. These are not considered to be a
-Collection in their own right. Each Collection is identified by the value of `projectMD/@xml:id` in its `wdbmeta.xml`.
-Hence, this value MUST be globally unique. This is not enforced, though, as importing projects, e. g. via git, may
-introduce duplicates that are more easily identified and handled from within the DB.
-
-## Resource
-While a resource can be anything that is stored in the DB, this term is narrowed down here. A Resource is anything that
-is identified by an ID in a `wdbmeta.xml`. This includes that file itself and usually every XML file that is intended to
-be displayed. In this case, the value of `file/@xml:id` in `wdbmeta.xml` MUST be equal to the value of `@xml:id` on the
-top level element of the XML file, e. g. `doc('wdbmeta.xml')//file/@xml:id = doc('tei.xml')/TEI/@xml:id`. Access to
-Resources is by their ID, be that for any retrieval via [[REST|REST-endpoints]] or for display via `view.html`. Hence, a
-file’s ID MUST be globally unique. Again, this is not enforced but an error will be generated if more than one resource
-is found with any given ID.
\ No newline at end of file
diff --git a/doc/Project-specifics.md b/doc/Project-specifics.md
deleted file mode 100644
index e0206c97..00000000
--- a/doc/Project-specifics.md
+++ /dev/null
@@ -1,48 +0,0 @@
-# Project specifics
-While this app aims at making available many default scripts so that any project can start by just uploading XML files, most projects will want to add some specific scripts or change the layout.
-In order to achieve this without affecting other projects, this app provides several levels of customization.
-Global scripts should remain unchanged.[1](#f1)
-By default, the template loads global CSS files (namely, `wdb.css` and either `view.css` for `view.html` or
-`function.csss` for other pages) and the global `function.js`.
-These provide the basic layout and functionality of the app. An overview of what is defined globally can be found in [[the list of CSS files and classes|css-files-and-classes]] and [[the list of JS functions|js-functions]]
-
-## Simple extension: `project.css` and `project.js`
-If your needs for adaptation are not too complex or you have some changes that you need for all files in a Project, each
-Project (i. e. any collection with an own `project.xqm`) can have customized CSS and JS files. A file called
-`project.css` or `project.js`, respectively, located in `{$project}/resources` (that is, as collection called
-`resources` that is located “next to” `project.xqm`) will be automatically imported _after_ loading the
-global scripts (`wdb.css`, `view.css`/`function.css`, or `function.js`) – this means you can simply override any style
-or function definition given globally. Keep in mind, though, that if you override any of these, especially the
-JavaScript functions, you are responsible to implement their functionality yourself should you want to keep
-it.[2](#f2)
-
-## Adapting function pages
-Pages using the `function.html` template (such as `start.html`, `search.html` or `query.html`) will load a `projectFunction.css` and/or `projectFunction.js` file in the project’s `resources` collection if available. This can be used for anything that is common to all variants of function pages.
-For each page, the can also be more specific files, e.g. `projectSearch.css`/`projectSearch.js` etc.
-For [[start.html]], there are additional options to create a start page.
-
-## Complex extensions
-If the selection of a CSS or JS is more complex than allowed for by the methods above, for example if you need different
-CSS files for introductions and transcriptions, you can select these by means of an XQuery function in [[project.xqm]].
-The files loaded by this method will be loaded last, meaning you can override any definition you made in `project.css`
-or `project.js`. Additionally, these can point anywhere while the “generic specifics” need to reside in
-`{$project}/resources`.
-
-This mechanism should give you sufficient freedom to adapt the layout of any project to the specific needs.
-
-## Queries with templating
-In order to easily use templating with any XQuery within a project, queries can be called via `query.html`. Such an
-XQuery script MUST be a module in [[namespace `wdbq`|list-of-namespaces]] and implement a function
-`wdbq:query($map as map(*))` and SHOULD implement `wdbq:getTask()`.
-
-The URL should look like this: `query.html?id={$projectID}&q={$pathToQueryWithinProject}&p={$additionalParameters}`.
-Parameters `q` and `p` can be accessed via `$model` by `wdbq:query($model)`. Parameter `p` MUST be a JSON object
-and will be parsed into a `map(*)`.
-
----
-
-1. While it is possible to adapt the global XSLT, CSS and JavaScript files – e. g. to make sure all
-projects use the same layout –, you should keep in mind that these may be replaced during an update or upgrade. If you
-make changes, be sure to save them to a location outside of `{$approot}/resources`. [↩](#a1)
-1. This means that if, for instance, you want to change the function to display footnotes, you have to
-implement all the steps necessary. JavaScript does not work in a cascading way as does CSS. [↩](#a2)
\ No newline at end of file
diff --git a/doc/Project.xqm.md b/doc/Project.xqm.md
deleted file mode 100644
index 7a2d0862..00000000
--- a/doc/Project.xqm.md
+++ /dev/null
@@ -1,24 +0,0 @@
-## General
-`project.xqm` is the central file controlling how a project is displayed. By implementing the functions described below, you can load special JavaScript and CSS files (useful if your needs can't be met by simple project.css/project.js), adapt how the title is displayed (in the HTML `header`), or adjust the project's start page (as displayed by `start.html`).
-To help maintaining a clean structure and a common page layout, `project.xqm` is cascading: if none is present in a project's collection, the search continues upwards. If all of your projects share the settings available here, you might be able to just have one `project.xqm` in your data collection.
-
-## Functions in project.xqm
-While none of these functions has to be implemented, at least `wdbPF:getHeader` should be present to display a meaningful head.
-See also [[project specific layout and functions|project-specifics]].
-
-### wdbPF:getProjectFiles($model)
-return `html:link` and `html:script` elements to be included in the `html:head`.
-
-### wdbPF:getHeader($model)
-return the content for `html:header`: one `html:h1`, one `html:h2` and 0+ `html:span` with class 'dispOpts' for links used all over the project.
-
-### wdbPF:getImages($id, $page)
-return the full path for the image of $page in document $id – used in the creation of an IIIF manifest.
-
-### wdbPF:getStart($model)
-return a sequence of nodes that will be the right hand side of `start.html`.
-
-### wdbPF:getNavXSLT()
-return an `xs:anyURI` pointing to the XSLT that should be used to transform the response of `nav.xql` for displaying the navigation. This is only necessary if there is no `vav.xsl` present in the project collection and you don't want to use the global stylesheet ad `wdb:edocBaseDB/resources/nav.xsl`.
-
-### wdbPF:getRestView
\ No newline at end of file
diff --git a/doc/REST-endpoints.md b/doc/REST-endpoints.md
deleted file mode 100644
index 97cec4c1..00000000
--- a/doc/REST-endpoints.md
+++ /dev/null
@@ -1,46 +0,0 @@
-**This is a documentation of what’s to come! The endpoints as described here are currently under development and may not yet be available or may still contain bugs!**
-
-The base URL for these endpoints is `{$server}/restxq/edoc/`.
-
-# rest-coll.xql
-|Endpoint|Method|Data Type|Data schema|action|
-|--|--|--|--|--|
-|**collection**|GET|XML, JSON|-|get a list of all projects (as defined by a collection with a `wdbmeta.xml`) and their subprojects – the IDs are those available for calls to `collection/${id}`. The data type is XML by default and subject to content negotiation|
-|**collection.xml**|GET|XML|-| ––"–– |
-|**collection.json**|GET|JSON|-| ––"–– |
-|**collection/${id}/wdbmeta.xml**|GET|XML|wdbmeta:projectMD|returns the project’s meta data file ; a project is identified by `wdbmeta:projectMD/@xml:id`|
-|**collection/${id}**|GET|XML, JSON|list|use content negotiation to get the result of the next 2|
-|**collection/${id}/resources.xml**|GET|XML|list|get a list of all collections and resources with an ID in the project identified by `$id`|
-|**collection/${id}/resources.json**|GET|JSON|list|get a list of all collections and resources with an ID in the project identified by `$id`|
-|**collection/${id}/collections.xml**|GET|XML|list|get a list of all subcollections recursively in the project identified by `$id`|
-|**collection/${id}/collections.json**|GET|JSON|list|get a list of all subcollections recursively in the project identified by `$id`|
-
-|**collection/${id}/nav.xml**|GET|XML|wdbmeta:struct|return the navigation for the given project. All children structs are returned and for all other projects, their hierarchy|
-|**collection/${id}/nav.html**|GET|HTML|html:ul|the result of the former transformed by either a project specific or a generic XSLT|
-
-# rest-files.xql
-|Endpoint|Method|Data Type|Data schema|action|
-|--|--|--|--|--|
-|**resource/${id}**|GET|-|-|return the file identified by `$id` in whatever datatype it is present in the DB. A file’s ID is listed in `wdbmeta.xml` (or for TEI files, in `/tei:TEI/@xml:id`)|
-|**resource/${id}/f/${fragment}**|GET|-|-|return whatever is identified by $fragment in $id (as above). In most cases, this will be an element with an `@xml:id` in an XML file (but it can be anything that is by a schema defined as an ID)|
-|**resource/${id}/views**|GET|XML, JSON|(list)|-|return a list of views that are available for this file (e.g., „HTML“) – this is given by the processes defined in `wdbmeta.xml`|
-|**resource/${id}/view.xml**|GET|XML|(list)|-|return a list of views that are available for this file (e.g., „HTML“) – this is given by the processes defined in `wdbmeta.xml`|
-|**resource/${id}/view.json**|GET|JSON|(list)|-|return a list of views that are available for this file (e.g., „HTML“) – this is given by the processes defined in `wdbmeta.xml`|
-|**resource/view/${id}.${type}**|GET|-|-|return the result of applying the process identified by $type (e.g. html) to the file identified by $id; may optionally take `?view=` if there are distinctions to be passed to the XSLT|
-|**resource/iiif/${id}.json**|GET|JSON|IIIF manifest|return a IIIF manifest for this file if it is an edition file|
-|**resource/iiif/${id}/${image}.json**|GET|JSON|IIIF image descriptor|return a IIIF image descriptor for the image identified by $image in the edition file identified by $id|
-
-# rest-search.xql
-|Endpoint|Method|Data Type|Data schema|action|
-|--|--|--|--|--|
-|**search/collection/{$id}.xml**|GET|XML|results/result|full text search of the collection with the given ID. The search string is to be sent URL encoded in parameter `q`; an offset can be given in parameter `start`; additional parameters can be passed as a simple map in `p`.|
-|**search/collection/{$id}.html**|GET|HTML|ul|full text search of the collection with the given ID. The search string is to be sent URL encoded in parameter `q`; an offset can be given in parameter `start`; additional parameters can be passed as a simple map in `p`. Results are produced by a (probably project specific) search.xsl |
-|**search/file/{$id}.xml**|GET|XML|results/result|full text search in the resource with the given ID. The search string is to be sent URL encoded in parameter `q`; an offset can be given in parameter `start`; additional parameters can be passed as a simple map in `p`.|
-|**search/file/{$id}.html**|GET|HTML|ul|full text search of the resource with the given ID. The search string is to be sent URL encoded in parameter `q`; an offset can be given in parameter `start`; additional parameters can be passed as a simple map in `p`. Results are produced by a (probably project specific) search.xsl |
-
-# rest-anno.xql
-|Endpoint|Method|Data Type|Data schema|action|
-|--|--|--|--|--|
-|**anno/{$fileID}**|GET|JSON| - |get all private annotations for the currently logged in user and all public annotations for the file identified by `$fileID`.|
-|**anno/{$fileID}** | POST | JSON | array: **from**, to, **text** | post one full text annotation for the file identified by `$fileID`.|
-|**anno/{$fileID}/word**|POST|JSON|array: **ID**, **job**, **text**|change the token with the given ID. job may be one of `edit`|
\ No newline at end of file
diff --git a/doc/Request-parameters.md b/doc/Request-parameters.md
deleted file mode 100644
index 4b1f0df3..00000000
--- a/doc/Request-parameters.md
+++ /dev/null
@@ -1,15 +0,0 @@
-##Common parameters
-The following [[main HTML files|main-html-files]]
-
-- `.../edoc/view.html?`
-- `.../edoc/query.html?`
-- `.../edoc/search.html?`
-- `.../edoc/start.html?`
-
-all use the the `id` parameter to identify a project or file.
-
-Some pages and functions may support the `ed` parameter that supplies a relative path to a project. As of March 2019, though, this parameter is deprecated and is likely to be removed. If both `ed` and `id` are present, the `id` parameter will take precedence. To avoid surprises, you should ensure that only one is used in any page call, though.
-
-##Additional parameters
-Some function pages (e. g. `query.html`) support and additional parameters `p`. It MUST have the form of a JSON object
-and will be parsed as a `map(*)` in `$model("p").
\ No newline at end of file
diff --git a/doc/Writing-scripts-to-display-XML-files.md b/doc/Writing-scripts-to-display-XML-files.md
deleted file mode 100644
index b319fe6c..00000000
--- a/doc/Writing-scripts-to-display-XML-files.md
+++ /dev/null
@@ -1,7 +0,0 @@
-# What scripts need to do
-Currently, `XSLT` is the only type script that is well-supported by the app. XQuery and others might follow if the need arises.
-
-As the app already provides an HTML frame (by means of eXist’s templating system, see [[Main-HTML-files]]), any script generating HTML output does not need to concern itself with the HTML header, the head portion or the display area for annotations and images on the right. Instead, all that needs to be done is generate a (series of) div(s) that will live inside the `html:main` displayed on the left.
-
-# How to specify which script to use
-The script to use is best specified within [[wdbmeta.xml]]. It is possible to supply a parameter `view` that will be passed to the script as a paramter `$view`.
\ No newline at end of file
diff --git a/doc/XQ-functions.md b/doc/XQ-functions.md
deleted file mode 100644
index e1dc2103..00000000
--- a/doc/XQ-functions.md
+++ /dev/null
@@ -1,16 +0,0 @@
-## List of XQuery functions for use in custom functions
-
-The following is an (incomplete) list of the public functions declared within the app.
-These might be helpful for your own scripts.
-A more detailed description is available in eXist's function documentation.
-If it has been properly generated, it should also provide content completion in eXide.
-
-### app.xql
-
-|function|use|
-|--|--|
-|`wdb:populateModel($id, $view, $model)`|Add more information to `$model` for use in other functions.|
-|`wdb:getUrl($path)`|Return a full URL for a relative DB path.|
-|`wdb:getEdPath($path, $absolute)`|Return the (relative or absolute) path to a resource.|
-|`wdb:findProjectFunction($model, $name, $arity)`|Returns true if the project with the path given in `$model("pathToEd")` has a [[project.xqm]] which declares a public function `$name` (the name is to be the local name only) with `$arity` parameters.|
-|`wdb:eval($function)`|Calls `util:eval($function)` and is subject to the same constraints (especially, the function name needs to be prefixed here; for project specifics: “wdbPF”); as this is within the scope of `app.xql`, it works immediately after calling `wdb:findProjectFunction` and also from another XQuery (while calling `util:eval` from another file will not work as the import is out of scope).|
\ No newline at end of file
diff --git a/doc/_Sidebar.md b/doc/_Sidebar.md
deleted file mode 100644
index e4394854..00000000
--- a/doc/_Sidebar.md
+++ /dev/null
@@ -1,23 +0,0 @@
-* Installation and Configuration
- * [[Global configuration options|Global-Configuration]]
-* Basic Usage
- * [[Basic collection structure|Basic-collection-structure]]
- * [[Identifying projects and files|Naming,-finding,-and-identifying-projects-and-files]]
- * [[Main files|Main-files]]
- * [[Main HTML files|Main-HTML-files]]
- * [[wdbmeta.xml]]
-* project Specifics
- * [[Project-specific settings and functions|Project-specifics]]
- * [[Project.xqm]]
- * [[Writing scripts to display XML files|Writing-scripts-to-display-XML-files]]
- * [[start.html]]
- * [[view.html]]
- * [[How to include an image viewer via project Specifics|Include-an-image-viewer-via-projectSpecifics]]
-* Tech
- * [[List of pre-defined CSS files and classes|CSS-files-and-classes]]
- * [[List of globally available variables|Global-variables]]
- * [[List of pre-defined JavaScript functions|JS-functions]]
- * [[List of namespaces|List-of-namespaces]]
- * [[List of pre-defined request parameters|Request-parameters]]
- * [[Documentation of REST endpoints|REST-endpoints]]
- * [[List of pre-defined XQuery functions|XQ-functions]]
\ No newline at end of file
diff --git a/doc/start.html.md b/doc/start.html.md
deleted file mode 100644
index 76ea2183..00000000
--- a/doc/start.html.md
+++ /dev/null
@@ -1,38 +0,0 @@
-(This information is correct for version 2.0 – 22Q1)
-
-## How to customize
-
-By default, `start.html` is contructed as follows:
-
-- the header uses the application title as specified in `wdbmeta.xml`
-- the left is a navigation the generation of which can be changed by [[Project-specifics]]
-- the right is a generic display of text and images which can also be adapted as needed
-
-It is possible to overwrite the default behaviour in several ways:
-- By default, the contents on the right are created from `wdbmeta.xml` by a generic XSLT,
- `{$edocBaseDB}/resources/start.xsl`. This can be overridden or extended (via `xsl:import`) by an instance specific
- global XSLT, `{$wdb:data}/resources/start.xsl`.
-- Use HTML templates in the project's `resoucres` folder (see [[Project-specifics]] for details) named
- `startHeader.html`, `startLeft.html`, and/or `startRight.html` respectively; if used, each file should contain the
- contents to be displayed in a single `html:div`.
-- Use [[Project-specifics]] by implementing `wdbPF:getStartHeader()`, `wdbPF:getStartLeft()`, and/or `wdbPF:getStart()`.
-
-The preferred mechanism is to write a global extension to `start.xsl` as this maintains consistency across all projects
- and requires the meta data in `wdbmeta.xml` to be up-to-date.
-
-If you really want to adjust `start.html` on a by-project basis, all three approaches. The order is 1. project specific
- HTML; 2. functions `wdbPF:*()` in `project.xqm`; 3. `{$wdb:data}/resources/start.xsl` for the right hand side; 4.
- `{$wdb:edocBaseDB}/resources/start.xsl` for the right hand side.
-
-Similar to the mechanism in [[Project-specifics]], after the generic and global `start.css` and `function.js` are
- loaded, `projectStart.css` and `projectStart.js` are being searched for in `{$pathToEd}/resources/`. You can create
- one or both and overwrite any settings/functions you like to style `starthtml` to your needs.
-
-## A word on images
-
-Images are loaded from the URLs given in `//meta:coverImages/meta:image/@href`. It is possible to have multiple images
- in here. The CSS is prepared in such a way that all images `.slideImage` will be centered within `.slideContainer`.
- However, there is no further styling (esp. no animation) as these will differ between projects and e.g. the number of
- images included. To facilitate e.g. a simple slider, though, the images are `position: absolute` within the container.
- A `max-height: 40vh` and `max-width: 40%` should take care of most needs for animations etc. but you can of course
- use any setting you may need in a global `start.css` or `projectStart.css`.
\ No newline at end of file
diff --git a/doc/view.html.md b/doc/view.html.md
deleted file mode 100644
index 76028bb4..00000000
--- a/doc/view.html.md
+++ /dev/null
@@ -1,7 +0,0 @@
-By using standard [[project-specifics]], the functions and styling of any resource displayed via `view.html` can be changed to a project’s needs.
-There are 2 more options to extend `view.html`:
-
-1. a file `projectFooter.html` in the project’s resource collection or a function `wdbPF:getProjectFooter` will be included as a footer below the text content on the left (and similarly in all pages created by using the function.html template);
-1. a file `projectRightFooter.html` in the project’s resource collection or a function `wdbPF:getProjectRightFooter` will be included on the right (after `#fac`); this can e.g. be used to attach a viewer.
-
-If both an HTML file and a function are present, the HTML file will take precedence.
\ No newline at end of file
diff --git a/doc/wdbmeta.xml.md b/doc/wdbmeta.xml.md
deleted file mode 100644
index 862cd989..00000000
--- a/doc/wdbmeta.xml.md
+++ /dev/null
@@ -1,39 +0,0 @@
-## Introduction to wdbmeta.xml
-
-A fully detailed description of `wdbmeta.xml` is available in the XML Schema available in `{$approot}/include/wdbmeta`.
-This documentation will cover the most important parts and how the file is evaluated in the app.
-
-Evey project should have a `wdbmeta.xml` file. This is also true about the main data collection.
-`wdbmeta.xml` is intended to replace `mets.xml` with a less verbose format while maintaining its functionality as a table of contents for a project.
-While it is possible to solely rely on a `mets.xml`, the app is designed with `wdbmeta.xml` in mind.
-Especially when it comes to rules for processing files, `wdbmeta.xml` is a lot easier to work with than a `mets.xml`.
-
-The files main element in `projectMD` in the namespace `https://github.com/dariok/wdbplus/wdbmeta`.
-
-## Main settings
-|element|max. allowed|usage|
-|--|--|--|
-|projectID|1|A globally unique ID for this project. While it is not a requirement, this value should equal `/projectMD/@xml:id` unless the difference has some meaning within the current instance of the app.|
-|titleData|1|Groups together the main information about the original text(s) contained in the project.|
-|titleData/title|+|The main title for this (sub-)project.|
-|titleData/date|* |A date that refers to the creation of the texts, e.g. 'from' and 'to'.|
-|titleData/place|* |A place relevant for the original texts, e.g. place of creation.|
-|titleData/language|* |An ISO 639-code for the languages (and scripts) used in the texts.|
-|titleData/type|1|A short documentation of the type(s) of text contained in the project.|
-|metaData|1|Groups together the meta data for the project|
-|metaData/contentGroup|1|Groups the types of content the project has|
-|metaData/contentGroup/content|+|A description of one type of content. `@xml:id` is mandatory.|
-|metaData/involvement|1|Groups information about all parties involved in the project|
-|metaData/involvement/org|* |Information about one organisation. Should contain `@contribution` with reference to a `content` element describing to which types of content the org contributed to.|
-|metaData/involvement/person|* |Information about one person. Should contain `@contribution` with reference to a `content` element describing to which types of content the person contributed to.|
-|metaData/legal|1|Groups licencing information.|
-|metaData/legal/licence|+|Contains info about a licence, a link to the full text and references to `content` elements in `@content`.|
-|files|1|Groups metadate about all files containted within the project.|
-|files/fileGroup|* |Groups file elements together for purposes of processing or simply clarity of organisation.|
-|files/file|+|Information about one file. Must have an `@xml:id` and `@path` and should have a `@uuid` and `@date`.|
-|process|+|Groups instructions how files are to be processed. Should have `@target` to specify the target format.|
-|process/command|+|Command point to scripts etc. that are to be executed with a file as input. Commands may have an attribute to specify which files are to be processed by this command. The first matching command is executed, while the last in the list is always the default.|
-|struct|1|Groups together files in a TOC.|
-|struct/import|1|Import another wdbmeta, ussually of the parent, to generate several levels of a TOC.|
-|struct/struct|+|Additional levels to the TOC.|
-|struct/view|+|One TOC entry; needs `@file` to point to a `file` and a `@label`.|
\ No newline at end of file
diff --git a/edoc/admin/admin.xqm b/edoc/admin/admin.xqm
index ed968eac..7f9aaa44 100644
--- a/edoc/admin/admin.xqm
+++ b/edoc/admin/admin.xqm
@@ -8,8 +8,6 @@ import module namespace wdb = "https://github.com/dariok/wdbplus/wdb" a
import module namespace wdbErr = "https://github.com/dariok/wdbplus/errors" at "/db/apps/edoc/modules/error.xqm";
declare namespace meta = "https://github.com/dariok/wdbplus/wdbmeta";
-declare namespace mets = "http://www.loc.gov/METS/";
-declare namespace mods = "http://www.loc.gov/mods/v3";
declare namespace sm = "http://exist-db.org/xquery/securitymanager";
(:~
@@ -22,19 +20,13 @@ declare
%templates:default("ed", "")
function wdbAdmin:start ( $node as node(), $model as map(*), $ed as xs:string ) {
try {
- let $pathToEd := if ( $ed = "" ) then
- $wdb:data
- else
- wdb:getEdPath($ed, true())
+ let $pathToEd := if ( $ed = "" )
+ then $wdb:data
+ else wdb:getEdPath($ed, true())
- (: The meta data are taken from wdbmeta.xml or a mets.xml as fallback :)
+ (: The meta data are taken from wdbmeta.xml :)
let $infoFileLoc := wdb:getMetaFile($pathToEd)
-
- let $title :=
- (
- normalize-space((doc($infoFileLoc)//meta:title)[1]),
- normalize-space((doc($infoFileLoc)//mods:title)[1])
- )[1]
+ , $title := normalize-space((doc($infoFileLoc)//meta:title)[1])
return map {
"ed": if ( $pathToEd = $wdb:data ) then "data" else $ed,
diff --git a/edoc/admin/projects.xqm b/edoc/admin/projects.xqm
index 4c7e8f87..0400a10f 100644
--- a/edoc/admin/projects.xqm
+++ b/edoc/admin/projects.xqm
@@ -9,7 +9,6 @@ import module namespace xstring = "https://github.com/dariok/XStringUtils" at
declare namespace config = "https://github.com/dariok/wdbplus/config";
declare namespace meta = "https://github.com/dariok/wdbplus/wdbmeta";
-declare namespace mets = "http://www.loc.gov/METS/";
declare namespace tei = "http://www.tei-c.org/ns/1.0";
declare function wdbPL:pageTitle ($node as node(), $model as map(*)) {
@@ -98,10 +97,7 @@ declare function wdbPL:body ( $node as node(), $model as map(*) ) {
declare function local:getFiles($model) {
let $infoFile := doc($model?infoFileLoc)
- let $filesInEd := (
- $infoFile//meta:file,
- $infoFile//mets:file
- )
+ , $filesInEd := $infoFile//meta:file
return
@@ -116,7 +112,7 @@ declare function local:getFiles($model) {
{
for $doc in $filesInEd
- let $info := if ($doc[self::meta:file])
+ let $info := if ( $doc[self::meta:file] )
then
let $id := $doc/@xml:id
let $view := $infoFile//meta:view[@file = $id]
@@ -128,17 +124,7 @@ declare function local:getFiles($model) {
$model?pathToEd || "/" || $doc/@path,
$view/@label
)
- else
- let $id := $doc/@ID
- let $struct := $infoFile//mets:fptr[@FILEID = $id]/parent::tei:div
- return (
- $id,
- if ($struct/@ORDERLABEL castable as xs:int)
- then number($struct/@ORDERLABEL)
- else string($struct/@ORDERLABEL),
- $model?pathToEd || "/" || $doc/mets:FLocat/@*:href,
- $struct/@LABEL
- )
+ else ()
order by $info[3]
return
diff --git a/edoc/config/edoc/data/collection.xconf b/edoc/config/edoc/data/collection.xconf
index add9e0d2..503ecb9a 100644
--- a/edoc/config/edoc/data/collection.xconf
+++ b/edoc/config/edoc/data/collection.xconf
@@ -1,5 +1,5 @@
-
+
@@ -34,7 +34,7 @@
-
+
@@ -59,10 +59,7 @@
-
-
-
-
+
@@ -79,7 +76,7 @@
-
+
diff --git a/edoc/entity.html b/edoc/entity.html
index 3eee12b9..c7e68916 100644
--- a/edoc/entity.html
+++ b/edoc/entity.html
@@ -1,11 +1,5 @@
-
-
-
-
-
-
-
-
Kilroy was here
-
+
+
+
Kilroy was here
-
\ No newline at end of file
+
diff --git a/edoc/expath-pkg.xml b/edoc/expath-pkg.xml
index 7b21c517..fe43428b 100644
--- a/edoc/expath-pkg.xml
+++ b/edoc/expath-pkg.xml
@@ -1,4 +1,4 @@
-
+W. Digitale Bibliothek
-
+
diff --git a/edoc/modules/addin.xqm b/edoc/modules/addin.xqm
index 866b1916..606dc0fe 100644
--- a/edoc/modules/addin.xqm
+++ b/edoc/modules/addin.xqm
@@ -11,10 +11,10 @@ import module namespace wdbErr = "https://github.com/dariok/wdbplus/errors" at "
declare namespace wdbadd = "https://github.com/dariok/wdbplus/addins";
(: load the main XQuery module for the requested addin. It is mandatory these implement wdbadd:main($map as map(*)) :)
-declare function wdbAddinMain:body($node as node(), $model as map(*)) {
+declare function wdbAddinMain:body ( $node as node(), $model as map(*) ) as element()+ {
let $addinName := substring-before(substring-after(request:get-uri(), 'addins/'), '/')
- let $path := $wdb:edocBaseDB || "/addins/" || $addinName || "/addin.xqm"
- let $map := map { "location-hints": $path }
+ , $path := $wdb:edocBaseDB || "/addins/" || $addinName || "/addin.xqm"
+ , $map := map { "location-hints": $path }
let $module := try {
load-xquery-module("https://github.com/dariok/wdbplus/addins", $map)
diff --git a/edoc/modules/app.xqm b/edoc/modules/app.xqm
index 444b2573..3f191fd6 100644
--- a/edoc/modules/app.xqm
+++ b/edoc/modules/app.xqm
@@ -21,10 +21,8 @@ import module namespace xstring = "https://github.com/dariok/XStringUtils"
declare namespace config = "https://github.com/dariok/wdbplus/config";
declare namespace main = "https://github.com/dariok/wdbplus";
declare namespace meta = "https://github.com/dariok/wdbplus/wdbmeta";
-declare namespace mets = "http://www.loc.gov/METS/";
declare namespace rest = "http://exquery.org/ns/restxq";
declare namespace tei = "http://www.tei-c.org/ns/1.0";
-declare namespace xlink = "http://www.w3.org/1999/xlink";
(: ALL-PURPOSE VARIABLES :)
(:~
@@ -53,7 +51,7 @@ declare variable $wdb:data :=
where contains($path, '.xml')
order by string-length($path)
return $path
-
+
return replace(xstring:substring-before-last($paths[1], '/'), '//', '/')
;
@@ -204,59 +202,68 @@ declare
%templates:default("view", "")
%templates:default("p", "")
function wdb:getEE($node as node(), $model as map(*), $id as xs:string, $view as xs:string, $p as xs:string) as item()* {
- let $newModel := wdb:populateModel($id, $view, $model, $p)
-
- let $pathParts := tokenize(replace($newModel?fileLoc, '//', '/'), '/')
- , $collection := string-join($pathParts[not(position() = last())], '/')
- , $dateTime := xmldb:last-modified($collection, $pathParts[last()])
- , $adjusted := adjust-dateTime-to-timezone($dateTime,"-PT0H0M")
- , $modifiedWithoutMillisecs := xs:dateTime(format-dateTime($adjusted, "[Y]-[M01]-[D01]T[H01]:[m]:[s]Z"))
- , $last-modified := format-dateTime($adjusted, "[FNn,3-3], [D00] [MNn,3-3] [Y] [H01]:[m]:[s] GMT")
+ try {
+ let $newModel := wdb:populateModel($id, $view, $model, $p)
- let $requestedModified := (
- request:get-attribute("if-modified"),
- request:get-header("If-Modified-Since")
- )[1]
- , $requestedModifiedParsed := parse-ietf-date($requestedModified)
-
- (: TODO: use a function to get the actual content language :)
- return if ( count($newModel) = 1
- and (
- $requestedModifiedParsed lt $modifiedWithoutMillisecs
- or empty($requestedModified)
- or $requestedModified = ''
- ) ) then
- (
- response:set-header("Last-Modified", $last-modified),
-
- {
- for $h in $node/* return
- if ( $h/*[@data-template] ) then
- for $c in $h/* return try {
- templates:apply($c, $wdb:lookup, $newModel)
- } catch * {
- util:log("error", $err:description)
- }
- else
- try {
- templates:apply($h, $wdb:lookup, $newModel)
- } catch * {
- util:log("error", $err:description)
- }
- }
-
- )
- else if ( $requestedModifiedParsed ge $modifiedWithoutMillisecs ) then
- response:set-status-code(304)
- else
-
-
-
-
An unknown error has occurred
-
-
- { util:log("error", $newModel) }
-
+ return if ( contains($newModel?fileLoc, 'http') ) then
+ $newModel
+ else
+ let $last-modified :=
+ wdbFiles:getModificationDate($newModel?filePathInfo?collectionPath, $newModel?filePathInfo?fileName)
+ => wdbFiles:ietfDate()
+
+ let $requestedModified := (
+ request:get-attribute("if-modified"),
+ request:get-header("If-Modified-Since")
+ )[1]
+ let $isModified := if ( $requestedModified != '' )
+ then wdbFiles:evaluateIfModifiedSince($id, $requestedModified)
+ else 200
+
+ (: TODO: use a function to get the actual content language :)
+ return if ( count($newModel) = 1 and $isModified = 200 )
+ then (
+ response:set-header("Last-Modified", $last-modified),
+
+ {
+ for $h in $node/* return
+ if ( $h/*[@data-template] ) then
+ for $c in $h/* return try {
+ templates:apply($c, $wdb:lookup, $newModel)
+ } catch * {
+ util:log("error", $err:description)
+ }
+ else
+ try {
+ templates:apply($h, $wdb:lookup, $newModel)
+ } catch * {
+ util:log("error", $err:description)
+ }
+ }
+
+ )
+ else if ( $isModified = 304 ) then
+ response:set-status-code(304)
+ else
+
+
+
+
An unknown error has occurred
+
+
+ { util:log("error", $newModel) }
+
+ } catch * {
+ util:log("error", $err:code || ': ' || $err:description),
+ wdbErr:error(map {
+ "code": $err:code,
+ "model": $model,
+ "err:value": $err:value,
+ "err:description": $err:description,
+ "err:additional": $err:additional,
+ "location": $err:module || '@' || $err:line-number || ':' || $err:column-number
+ })
+ }
};
(:~
@@ -272,29 +279,22 @@ declare function wdb:populateModel ( $id as xs:string, $view as xs:string, $mode
wdb:populateModel($id, $view, $model, "")
};
declare function wdb:populateModel ( $id as xs:string, $view as xs:string, $model as map(*), $p as xs:string ) as item()* {
- try {
- let $pTF := wdb:getFilePath($id)
- let $pathToFile := if ( sm:has-access($pTF, "r") )
- then $pTF
- else error(xs:QName("wdbErr:wdb0004"))
-
- let $pathToEd := wdb:getEdPath($id, true())
- let $pathToEdRel := substring-after($pathToEd, $wdb:edocBaseDB||'/')
-
- (: The meta data are taken from wdbmeta.xml or a mets.xml as fallback :)
- let $infoFileLoc := wdb:getMetaFile($pathToEd)
-
- let $ed := if (ends-with($infoFileLoc, 'wdbmeta.xml'))
- then string(doc($infoFileLoc)/meta:projectMD/@xml:id)
- else string(doc($infoFileLoc)/mets:mets/@OBJID)
+ let $filePathInfo := wdbFiles:getFullPath($id)
+ , $pathToFile := if ( map:keys($filePathInfo) = 'fileURL' )
+ then
+ $filePathInfo?fileURL
+ else
+ $filePathInfo?collectionPath || '/' || $filePathInfo?fileName
+ , $pathToEd := $filePathInfo?projectPath
+ , $infoFileLoc := $filePathInfo?projectPath || '/wdbmeta.xml'
- let $xsl := if ( contains($pTF, 'wdbmeta.xml') ) then
- (: TODO get path to XSL via function (use what’s in rest-files.xql) :)
- xs:anyURI($wdb:data || '/resources/nav.xsl')
- else if ( ends-with($infoFileLoc, 'wdbmeta.xml') ) then
- wdb:getXslFromWdbMeta($infoFileLoc, $id, 'html')
- else
- wdb:getXslFromMets($infoFileLoc, $id, $pathToEdRel)
+ let $ed := string(doc($infoFileLoc)/meta:projectMD/@xml:id)
+
+ let $xsl := if ( $filePathInfo?fileName = "wdbmeta.xml" )
+ then
+ (: TODO get path to XSL via function (use what’s in rest-files.xql) :)
+ xs:anyURI($wdb:data || '/resources/nav.xsl')
+ else wdb:getXslFromWdbMeta($infoFileLoc, $id, 'html')
let $xslt := if (doc-available($xsl))
then $xsl
@@ -324,6 +324,7 @@ declare function wdb:populateModel ( $id as xs:string, $view as xs:string, $mode
let $map := map {
"ed": $ed,
"fileLoc": $pathToFile,
+ "filePathInfo": $filePathInfo,
"functions": map { "project": $projectFunctions, "instance": $instanceFunctions },
"header": $header,
"id": $id,
@@ -340,17 +341,6 @@ declare function wdb:populateModel ( $id as xs:string, $view as xs:string, $mode
}
return $map
- } catch * {
- wdbErr:error(map {
- "code": $err:code,
- "pathToEd": $wdb:data,
- "ed": $wdb:data,
- "model": $model,
- "value": $err:value,
- "desc": $err:description,
- "location": $err:module || '@' || $err:line-number ||':'||$err:column-number
- })
- }
};
(: ~
@@ -497,7 +487,7 @@ declare function wdb:getContent($node as node(), $model as map(*)) {
return
try {
- { transform:transform(doc($file), doc($xslt), $params, $attr, "expand-xincludes=no") }
+ { transform:transform(doc($file), doc($xslt), $params, $attr, "") }
{ wdb:getLeftFooter($node, $model) }
} catch * { (util:log("error",
@@ -577,15 +567,28 @@ declare function wdb:getFilePath ( $id as xs:string ) as xs:string {
(: do not just return a random URI but add some checks for better error messages:
: no files found or more than one TEI file found or only wdbmeta entry but no other info :)
let $pathToFile := if ( count($files) = 0 ) then
- fn:error(fn:QName('https://github.com/dariok/wdbErr', 'wdb0000'), "no file with ID " || $id || " in " || $wdb:data)
+ error(
+ QName('https://github.com/dariok/wdbErr', 'wdb0000'),
+ "no file with ID " || $id || " in " || $wdb:data,
+ map { "id": $id, "request": request:get-url() }
+ )
else if ( count($files) > 1 ) then
- fn:error(fn:QName('https://github.com/dariok/wdbErr', 'wdb0001'), "multiple files with ID " || $id || " in " || $wdb:data)
+ error(
+ QName('https://github.com/dariok/wdbErr', 'wdb0001'),
+ "multiple files with ID " || $id || " in " || $wdb:data,
+ map { "id": $id, "request": request:get-url() }
+ )
else if ( local-name($files[1]) = 'id' ) then
base-uri($files[1]) || '#' || $id
else
xstring:substring-before-last(base-uri($files[1]), '/') || '/' || $files[1]
- return $pathToFile
+ return if ( starts-with($files[1], '$') )
+ then
+ let $peer := $files[1] => substring(2) => substring-before('/')
+ , $id := $files[1] => substring-after('/')
+ return $wdb:configFile/id($peer) || '/' || $id
+ else $pathToFile
};
(:~
@@ -597,8 +600,7 @@ declare function wdb:getFilePath ( $id as xs:string ) as xs:string {
: @returns the path (relative) to the app root
:)
declare function wdb:getEdPath($id as xs:string, $absolute as xs:boolean) as xs:string {
- let $file := (collection($wdb:data)/id($id)[local-name() = ('file', 'projectMD', 'struct', 'mets')],
- collection($wdb:data)//mets:file[@ID = $id])[1]
+ let $file := collection($wdb:data)/id($id)[self::meta:file or self::meta:projectMD or self::meta:struct]
let $edPath := if ( count($file) = 1 ) then
xstring:substring-before-last(base-uri($file), '/')
@@ -640,11 +642,8 @@ declare function wdb:getAbsolutePath ( $ed as xs:string, $path as xs:string ) {
: @return the ID of the project
:)
declare function wdb:getEdFromFileId ($id as xs:string) as xs:string {
- let $file := (collection($wdb:data)/id($id)[self::meta:file],
- collection($wdb:data)//mets:file[@ID = $id])[1]
- return if ($file[self::meta:file])
- then $file/ancestor::meta:projectMD/@xml:id
- else $file/ancestor::mets:mets/@OBJID
+ let $file := collection($wdb:data)/id($id)[self::meta:file]
+ return $file/ancestor::meta:projectMD/@xml:id
};
(: ~
@@ -667,12 +666,10 @@ declare function wdb:getEdFromPath($path as xs:string, $absolute as xs:boolean)
wdbErr:error(map{"code": "wdbErr:wdb2001", "additional": {$path}})
else for $p in $pa
order by string-length($p) descending
- let $p1 := $p || '/wdbmeta.xml'
- let $p2 := $p || '/mets.xml'
- return if (doc-available($p1) or doc-available($p2)) then $p else ()
+ return if ( doc-available($p || '/wdbmeta.xml') ) then $p else ()
- return if ($absolute)
+ return if ( $absolute )
then $path[1]
else substring-after($path[1], $wdb:edocBaseDB||'/')
};
@@ -789,14 +786,12 @@ declare function wdb:eval($function as xs:string, $cache-flag as xs:boolean, $ex
(:~
: Return the full path to the project collection by trying to find the meta file by the project ID
:
- : @param $ed The ID of a project, to be found in meta:projectMD/@xml:id or mets:mets/@OBJID
+ : @param $ed The ID of a project, to be found in meta:projectMD/@xml:id
: @return The path to the project
:)
declare function wdb:getProjectPathFromId ( $ed as xs:string ) as xs:string {
- let $md := (
- collection($wdb:data)/id($ed)[self::meta:projectMD],
- collection($wdb:data)/mets:mets[@OBJID = $ed]
- )
+ let $md := collection($wdb:data)/id($ed)[self::meta:projectMD]
+
return xstring:substring-before-last(base-uri(($md)[1]), '/')
};
@@ -804,10 +799,8 @@ declare function wdb:getProjectPathFromId ( $ed as xs:string ) as xs:string {
: Get the meta data file from the ed path
:)
declare function wdb:getMetaFile($pathToEd) {
- if (doc-available($pathToEd||'/wdbmeta.xml'))
+ if ( doc-available($pathToEd||'/wdbmeta.xml') )
then $pathToEd || '/wdbmeta.xml'
- else if (doc-available($pathToEd || '/mets.xml'))
- then $pathToEd || '/mets.xml'
else fn:error(fn:QName('https://github.com/dariok/wdbErr', 'wdbErr:wdb0003'))
};
@@ -817,7 +810,7 @@ declare function wdb:getMetaFile($pathToEd) {
: @param $ed The project ID to be evaluated
:)
declare function wdb:getMetaElementFromEd ( $ed as xs:string ) as element() {
- collection($wdb:data)/id($ed)[self::meta:projectMD or self::mets:mets]
+ collection($wdb:data)/id($ed)[self::meta:projectMD]
};
(: END GENERAL HELPER FUNCTIONS :)
@@ -856,40 +849,6 @@ declare function wdb:getXslFromWdbMeta ( $infoFileLoc as xs:string, $id as xs:st
(: As we check from most specific to default, the first command in the sequence is the right one :)
return ($sel)[1]/text()
};
-declare function wdb:getXslFromMets ($metsLoc, $id, $ed) {
- let $mets := doc($metsLoc)
- let $structs := $mets//mets:div[mets:fptr[@FILEID=$id]]/ancestor-or-self::mets:div/@ID
-
- let $be := for $s in $structs
- return $mets//mets:behavior[matches(@STRUCTID, concat('(^| )', $s, '( |$)'))]
- let $behavior := for $b in $be
- order by local:val($b, $structs, 'HTML')
- return $b
- let $trans := $behavior[last()]/mets:mechanism/@xlink:href
-
- return concat($wdb:edocBaseDB, '/', $ed, '/', $trans)
-};
-(: Try to find the most specific mets:behavior
- : $test: mets:behavior to be tested
- : $seqStruct: sequence of mets:div/@ID (ordered by specificity, ascending)
- : $type: return type
- : returns: a weighted value for the behavior's “rank” :)
-declare function local:val($test, $seqStruct, $type) {
- let $vIDt := for $s at $i in $seqStruct
- return if (matches($test/@STRUCTID, concat('(^| )', $s, '( |$)')))
- then math:exp10($i)
- else 0
- let $vID := fn:max($vIDt)
- let $vS := if ($test[@BTYPE = $type])
- then 5
- else if ($test[@LABEL = $type])
- then 3
- else if ($test[@ID = $type])
- then 1
- else 0
-
- return $vS + $vID
-};
(: we need a lookup function for the templating system to work :)
declare variable $wdb:lookup := function($functionName as xs:string, $arity as xs:int) {
diff --git a/edoc/modules/entity.xqm b/edoc/modules/entity.xqm
index 241837d1..301a2e07 100644
--- a/edoc/modules/entity.xqm
+++ b/edoc/modules/entity.xqm
@@ -1,239 +1,28 @@
-xquery version "3.0";
-(: erstellt 2016-07-26 Bearbeiter:DK Dario Kampkaspar :)
+xquery version "3.1";
module namespace wdbe = "https://github.com/dariok/wdbplus/entity";
import module namespace wdb = "https://github.com/dariok/wdbplus/wdb" at "app.xqm";
import module namespace console = "http://exist-db.org/xquery/console";
-declare namespace tei = "http://www.tei-c.org/ns/1.0";
+declare namespace tei = "http://www.tei-c.org/ns/1.0";
-(: $id ID-String of the entity to be displayed – must be globally unique
- $ed ID of the project from which specific information shall be drawn
- $reg a file containing a project specific tei:list*, if such information is requested :)
-declare function wdbe:getEntity($node as node(), $model as map(*), $id as xs:string, $ed as xs:string?, $reg as xs:string?, $xsl as xs:string?) as map(*) {
- (: TODO check calls; entry ID and project ID should be the only necessary parameters :)
- (: TODO support project specific views :)
+(: $ent ID-String of the entity to be displayed – must be globally unique
+ $ed ID of the project from which specific information shall be drawn :)
+declare function wdbe:getEntity ( $node as node(), $model as map(*), $ent as xs:string, $ed as xs:string ) as map(*) {
+ let $edPath := wdb:getEdPath($ed, true())
+ , $entry := collection($edPath || "/index")/id($ent)
- let $edPath := wdb:getEdPath($ed)
- let $regFile := $edPath || '/' || $reg
- let $testPath := $wdb:data || '/' || $ed || '/' || $reg
- let $entryEd := doc($wdb:data || '/' || $ed || '/' || $reg)/id($id)
- (: TODO: this only uses a project specific list* file; we want ot use (or at least support) globals files :)
-
- (: let $t := console:dump("default", ("edPath", "regFile", "testPath", "entryEd")) :)
- return map { "entry": $entryEd, "id": $id, "ed": $ed }
-};
-
-(: create the heading for the HTML snippet; 2016-08-17 DK :)
-declare function wdbe:getEntityName($node as node(), $model as map(*)) {
- let $entryEd := $model("entry")
- return
{
- typeswitch ($entryEd)
- case element(tei:person)
- return if ($entryEd/tei:persName[@type='index'])
- then wdbe:passthrough($entryEd/tei:persName[@type='index'], $model)
- else wdbe:shortName($entryEd/tei:persName[1])
- case element(tei:bibl)
- return wdbe:shortTitle($entryEd, $model)
- case element(tei:place)
- return normalize-space($entryEd/tei:placeName)
- default
- return name($entryEd[1])
- }
+ return map { "entry": $entry, "ent": $ent, "ed": $ed, "pathToEd": $edPath }
};
-declare function wdbe:getEntityBody($node as node(), $model as map(*)) {
- let $ent := $model("entry")
+declare function wdbe:getEntityBody( $node as node(), $model as map(*) ) as element() {
+ let $xsl := if ( doc-available($model?pathToEd || "/resources/tei-index.xsl") )
+ then doc($model?pathToEd || "/resources/tei-index.xsl")
+ else doc("/db/apps/edoc/resources/tei-index.xsl")
+ , $result := transform:transform($model?entry, $xsl, ())
- return wdbe:transform($ent, $model)
-};
-
-(: TODO replace by proper XSLT and the usual means of project specifics; 2019-08-23 DK :)
-declare function wdbe:transform($node, $model as map(*)) as item()* {
- typeswitch ($node)
- case text() return $node
- case element(tei:person) return
-
-
-
-
-
-
-
-
-
Person
-
- {wdbe:passthrough($node, $model)}
-
- case element(tei:org) return
-
-
-
-
-
-
-
-
-
Organisation / Körperschaft
-
- {wdbe:passthrough($node, $model)}
-
- case element(tei:persName) return wdbe:persName($node, $model)
- case element(tei:birth) return wdbe:bd($node, $model)
- case element(tei:death) return wdbe:bd($node, $model)
- case element(tei:floruit) return wdbe:bd($node, $model)
- case element(tei:listBibl) return wdbe:listBibl($node, $model)
- case element(tei:note) return wdbe:note($node, $model)
- case element(tei:bibl) return
- if ($node/ancestor::tei:person or count($node/ancestor::tei:place)>0) (: Literatur zu anderen Entitäten: Kurzausgabe :)
- then wdbe:listBiblBibl($node, $model)
- else wdbe:bibl($node)
- case element(tei:name) return
- if ($node/parent::tei:abbr)
- then {$node}
- else wdbe:passthrough($node, $model)
- case element(tei:title) return
- if ($node/parent::tei:abbr)
- then {string($node)}
- else wdbe:passthrough($node, $model)
- case element(tei:placeName) return
- if ($node/ancestor::tei:person)
- then wdbe:shortPlace($node)
- else wdbe:placeName($node)
- case element(tei:place) return
{wdbe:passthrough($node, $model)}
- case element(tei:idno) return wdbe:idno($node)
- case element(tei:occupation) return
-
-
{ if ( $node/@type ) then "Titel" else "Beruf" }
-
{ normalize-space($node) }
-
- case element(tei:orgName) return wdbe:persName($node, $model)
-
-(: default return wdbe:passthrough($node):)
- (:default return concat("def: ", name($node)):)
- default return $node
-};
-
-declare function wdbe:passthrough($nodes as node()*, $model) as item()* {
- if (count($nodes) > 1 or $nodes instance of text())
- then for $node in $nodes return wdbe:transform($node, $model)
- else for $node in $nodes/node() return wdbe:transform($node, $model)
-};
-
-(: die folgenden neu 2016-08-16 DK :)
-declare function wdbe:persName($node, $model) {
-
-
Name
-
{ normalize-space($node) }
-
-};
-
-declare function wdbe:names($node) {
-
-
{
- typeswitch($node)
- case element(tei:forename) return "Vorname"
- case element(tei:surname) return "Nachname"
- case element(tei:nameLink) return "Prädikat"
- case element(tei:roleName) return "Amt/Titel"
- case element(tei:genName) return ""
- case element(tei:addName) return wdbe:addName($node)
- default return local-name($node)
- }
-
{$node/text()}
-
-};
-
-declare function wdbe:addName($node) as xs:string {
-let $resp :=
- if ($node/@type = "toponymic") then 'toponymischer Beiname'
- else if ($node/@type = 'cognomen') then 'Cognomen'
- else "Beiname"
-
- return $resp
-};
-
-declare function wdbe:bd($node, $model) {
-
-
{
- typeswitch($node)
- case element(tei:birth) return "geb."
- case element(tei:death) return "gest."
- default return "lebte"
- }
-
{wdbe:passthrough($node, $model)}
-
-};
-
-declare function wdbe:listBibl($node, $model) {
-
-
Literatur
-
{
- for $bibs in $node return wdbe:passthrough($bibs, $model)
- }
-
-};
-
-(: Kurztitelausgaben in einer listBibl; 2016-08-17 DK :)
-declare function wdbe:listBiblBibl($node, $model) {
- if ($node/@ref) then
- let $id := substring-after($node/@ref, '#')
- let $entry := collection(concat('/db/', $model('ed')))/id($id)
-(: let $ln := $wdb:edocBaseURL || '/entity.html?id=' || $id || '&ed=' || $model('ed'):)
- let $ln := "javascript:show_annotation('" || $model('ed') || "', '/db/" || $model('ed') || "/register/bibliography.xml', '"
- || $wdb:edocBaseDB || "/resource/bibl.xsl', '" || $id || "', 0, 0);"
- return
-};
-
-(: Ausgabe einer bibliographischen Langangabe; 2016-08-17 DK :)
-declare function wdbe:bibl($node) {
- (: TODO erweitern für strukturierte Angaben! :)
-
{$node/node()[not(self::tei:abbr)]}
-};
-
-(: zur Ausgabe von Kurztiteln eines Buches; 2016-08-17 DK :)
-(: $node ein Element tei:bibl
- Ausgabe formatierter Kurztitel :)
-declare function wdbe:shortTitle($node, $model) {
- (: Kurztitel: Verarbeitung von tei:abbr. Evtl. enthaltenes tei:name in Kapitälchen, tei:title kursiv :)
- if ($node/tei:abbr) then wdbe:passthrough($node/tei:abbr, $model)
- else substring($node, 1, 50)
-};
-
-declare function wdbe:shortName($node) {
- {
- if ($node/tei:name) then $node/tei:name
- else
- let $tr := string-join(($node/tei:surname, $node/tei:forename), ", ")
- let $add := if ($node/tei:addName) then concat(' (', $node/tei:addName, ')') else ""
- return concat($tr, ' ', $node/tei:nameLink, $add)
- }
-};
-
-declare function wdbe:note($node, $model) {
-
Anmerkung
{wdbe:passthrough($node, $model)}
-};
-
-declare function wdbe:shortPlace($node) {
- (: TODO tei:head oder tei:label als Standardwert nutzen, falls vorhanden :)
- (: TODO ggfs. sind hier andere Arten zu berücksichtigen (tei:geogName) :)
- {replace($node/tei:placeName[1]/tei:settlement, '!', ', ')}
-};
-
-declare function wdbe:placeName($node) {
- (: TODO anpassen an ausführlichere Angaben :)
- if ($node/tei:country)
- then (
Name
{replace($node/tei:settlement, '!', ', ')}
,
-
Land
{string($node/tei:country)}
)
- else
Name
{replace($node/tei:settlement, '!', ', ')}
-};
-
-(: neu 2017-05-22 DK :)
-declare function wdbe:idno($node) {
-
+ return if ( count($result) = 1 )
+ then $result
+ else
Keine Informationen gefunden.
};
diff --git a/edoc/modules/error.xqm b/edoc/modules/error.xqm
index 6b9f30a3..bfa56cfc 100644
--- a/edoc/modules/error.xqm
+++ b/edoc/modules/error.xqm
@@ -2,17 +2,16 @@ xquery version "3.1";
module namespace wdbErr = "https://github.com/dariok/wdbplus/errors";
-import module namespace templates = "http://exist-db.org/xquery/html-templating";
import module namespace response = "http://exist-db.org/xquery/response" at "java:org.exist.xquery.functions.response.ResponseModule";
import module namespace map = "http://www.w3.org/2005/xpath-functions/map" at "java:org.exist.xquery.functions.map.MapModule";
-import module namespace console = "http://exist-db.org/xquery/console";
import module namespace functx = "http://www.functx.com" at "/db/system/repo/functx-1.0.1/functx/functx.xq";
-declare function wdbErr:error ($data as map (*)) {
- let $error := switch (xs:string($data("code")))
+declare function wdbErr:error ( $data as map (*) ) as item()+ {
+ let $error := switch ( xs:string($data("code")) )
case "wdbErr:wdb0000"
- case "wdb0000" return "No file could be found for the ID supplied in the request."
+ case "wdb0000"
+ return "No file could be found for the ID supplied in the request: " || $data("err:value")?id
case "wdbErr:wdb0001"
case "wdb0001" return "Multiple files were found for the ID supplied. Unable to determine which one to display."
case "wdbErr:wdb0002"
@@ -23,6 +22,8 @@ declare function wdbErr:error ($data as map (*)) {
case "wdb0004" return "The requested file is not readable by the current user."
case "wdbErr:wdb0200"
case "wdb0200" return "Project not found."
+ case "wdbErr:wdb0404"
+ return "file not found for path " || $data("err:value")?pathToFile
case "wdbErr:wdb1001"
case "wdb1001" return "An error occurred while applying the transformation."
case "wdbErr:wdb2001" return "Module not found."
@@ -32,24 +33,40 @@ declare function wdbErr:error ($data as map (*)) {
case "wdbErr:wdb3001" return "Error creating model in function.xqm"
default return "An unknown error has occurred: " || $data("code")
+ let $statusCode := if ( xs:string($data?code) = ("wdbErr:wdb0200", "wdbErr:wdb0000", "wdbErr:wdb0404") )
+ then 404
+ else 418
+
+ let $errorContent := if ( $statusCode = 404 )
+ then
+
+
Seite nicht gefunden
+
Leider konnten wir die angegebene Seite nicht finden
- } :)
else
};
@@ -120,11 +85,11 @@ declare function local:selectEd ($model) {(
let $md := doc($wdb:data || '/wdbmeta.xml')
let $opts := for $file in $md//meta:ptr
let $id := $file/@xml:id
- let $label := $md//meta:struct[@file = $id]/@label
+
return
return (
if ( count($opts) gt 1 ) then else (),
diff --git a/edoc/modules/stats.xqm b/edoc/modules/stats.xqm
index b1485434..ab5984a8 100644
--- a/edoc/modules/stats.xqm
+++ b/edoc/modules/stats.xqm
@@ -5,8 +5,6 @@ module namespace wdbs = "https://github.com/dariok/wdbplus/stats";
import module namespace wdb = "https://github.com/dariok/wdbplus/wdb" at "app.xqm";
import module namespace templates = "http://exist-db.org/xquery/html-templating";
-declare namespace mets = "http://www.loc.gov/METS/";
-declare namespace mods = "http://www.loc.gov/mods/v3";
declare namespace tei = "http://www.tei-c.org/ns/1.0";
declare namespace wdbc = "https://github.com/dariok/wdbplus/config";
declare namespace wdbmeta = "https://github.com/dariok/wdbplus/wdbmeta";
@@ -24,7 +22,6 @@ declare function wdbs:projectList($admin as xs:boolean, $ed) {
wdb:getEdPath($ed, true())
} catch * {()}
- let $editionsM := collection($pathToEd)//mets:mets
let $editionsW := collection($pathToEd)//wdbmeta:projectMD
return
@@ -32,51 +29,35 @@ declare function wdbs:projectList($admin as xs:boolean, $ed) {
Eintrag
Titel
- {if ($admin = true()) then
- (
-
Metadaten-Datei
,
-
verwalten
+ {
+ if ( $admin ) then (
+
Metadaten-Datei
,
+
verwalten
)
else ()
}
- {(
- for $mets in $editionsM
- let $name := $mets/mets:dmdSec[1]/mets:mdWrap[1]/mets:xmlData[1]/mods:mods[1]/mods:titleInfo[1]/mods:title[1]
- let $metsFile := document-uri(root($mets))
- let $id := wdb:getEdPath($metsFile)
- order by $id
- return
-
- )}
+ }
};
diff --git a/edoc/modules/wdb-files.xqm b/edoc/modules/wdb-files.xqm
index 9312f216..8579ea14 100644
--- a/edoc/modules/wdb-files.xqm
+++ b/edoc/modules/wdb-files.xqm
@@ -12,47 +12,96 @@ xquery version "3.1";
module namespace wdbFiles = "https://github.com/dariok/wdbplus/files";
-import module namespace functx = "http://www.functx.com" at "/db/system/repo/functx-1.0.1/functx/functx.xq";
+import module namespace functx = "http://www.functx.com" at "/db/system/repo/functx-1.0.1/functx/functx.xq";
declare namespace meta = "https://github.com/dariok/wdbplus/wdbmeta";
-declare namespace mets = "http://www.loc.gov/METS/";
declare namespace wdbErr = "https://github.com/dariok/wdbplus/errors";
-declare namespace xlink = "http://www.w3.org/1999/xlink";
(:~
: Return the path to all Resources with a given ID
:
- : This function looks within metadata files, i.e. wdbmeta.xml and mets.xml, and returns all paths found. If a file has
- : an xml:id but is not “registered” with its project’s metadata, it wont’t be returned. Also, this function will
- : return all files; it is up to the caller to act upon this accordingly.
+ : This function looks within a project’s metadata file, i.e. wdbmeta.xml, and returns all paths found. If a file has no
+ : xml:id or has an xml:id but is not “registered” with its project’s metadata, it wont’t be returned. Also, this
+ : function will return all files with a given ID; it is up to the caller to act upon this accordingly.
:
- : @param $collection as xs:string: ID of the collection in which to search
+ : @param $collection as xs:string: path the collection in which to search
: @param $id as xs:string: the ID value to be used
: @return attribute()* the path attributes to the files as stored in the meta data files
:)
- declare function wdbFiles:getFilePaths ( $collection, $id ) as attribute()* {
- (
- collection($collection)//id($id)[self::meta:file]/@path,
- collection($collection)//id($id)[self::meta:struct]/@xml:id,
- collection($collection)//mets:file[@ID = $id]/mets:FLocat/@xlink:href
+ declare function wdbFiles:getFilePaths ( $collection as xs:string, $id as xs:string ) as attribute()* {
+ let $candidates := collection($collection)//id($id)
+
+ return (
+ $candidates[self::meta:file]/@path,
+ $candidates[self::meta:struct]/@xml:id
)
};
(:~
: Return the absolute Path to the file identified by the path attribute
:
- : @param $path as attribute() an attribute node from wdbmeta or METS
+ : @param $path as attribute() an attribute node from wdbmeta
: @return xs:anyURI
:)
-declare function wdbFiles:getAbsolutePath ( $path as attribute() ) {
- let $base :=functx:substring-before-last(base-uri($path), '/')
- let $val := string($path)
+declare function wdbFiles:getAbsolutePath ( $path as attribute() ) as xs:anyURI {
+ let $base := functx:substring-before-last(base-uri($path), '/')
+ , $val := string($path)
- return if (starts-with($val, $base))
+ return if ( starts-with($val, $base) )
then xs:anyURI($val)
else xs:anyURI($base || '/' || $val)
};
+(:~
+ : return a map with the path to a file split into its parent collection (which may be different from the
+ : project collection) and its file name
+ :
+ : @param $id as xs:string: the ID of the file (which should be unique)
+ : @return map(string, string) with keys "collectionPath", "fileName", "projectPath"
+ : @throws wdbErr:wdb0000
+ : @throws wdbErr:wdb0001
+:)
+declare function wdbFiles:getFullPath ( $id as xs:string ) as map( xs:string, xs:string, xs:string? )? {
+ let $file := collection("/db")/id($id)[self::meta:file]
+
+ return if ( count($file) = 0 ) then
+ error(
+ QName('https://github.com/dariok/wdbErr', 'wdb0000'),
+ "no file with ID " || $id,
+ map { "id": $id, "request": request:get-url() }
+ )
+ else if ( count($file) > 1 ) then
+ error(
+ QName('https://github.com/dariok/wdbErr', 'wdb0001'),
+ "multiple files with ID " || $id,
+ map { "id": $id, "request": request:get-url() }
+ )
+ else if ( $file[self::meta:projectMD] ) then
+ let $projectPath := base-uri($file) => substring-before("wdbmeta.xml")
+ return map {
+ "projectPath": $projectPath,
+ "collectionPath": $projectPath,
+ "fileName": "wdbmeta.xml"
+ }
+ else if ( starts-with($file/@path, '$') ) then
+ let $projectPath := base-uri($file) => substring-before("wdbmeta.xml")
+ , $peer := $file => substring(2) => substring-before('/')
+ , $id := $file => substring-after('/')
+ return map {
+ "projectPath": $projectPath,
+ "fileURL": doc("../config.xml")/id($peer) || '/' || $id
+ }
+ else
+ let $projectPath := base-uri($file) => substring-before("wdbmeta.xml")
+ , $path := $projectPath || $file/@path
+
+ return map{
+ "projectPath": $projectPath,
+ "collectionPath": functx:substring-before-last($path, '/') ,
+ "fileName": functx:substring-after-last($path, '/')
+ }
+};
+
(:~
: Check whether the current user has the right to access the file with the given mode
:
@@ -72,3 +121,58 @@ declare function wdbFiles:hasAccess ( $collection as xs:string, $id as xs:string
return if (sm:has-access($path, $mode)) then $path else false()
else error(xs:QName("wdbErr:wdb0001"))
};
+
+(:~
+ : Return the modification date adjusted to GMT, without milliseconds
+ :
+ : @param $collectionPath xs:string path to the base collection
+ : @param $id xs:string ID of the file
+ : @return xs:dateTime
+ :)
+declare function wdbFiles:getModificationDate ( $id as xs:string ) as xs:dateTime {
+ let $path := wdbFiles:getFullPath($id)
+
+ return wdbFiles:getModificationDate($path?collectionPath, $path?fileName)
+};
+
+(:~
+ : Return the modification date adjusted to GMT, without milliseconds
+ :
+ : @param $collectionPath xs:string path to the base collection
+ : @param $fileName xs:string the name of the file
+ : @return xs:dateTime
+ :)
+declare function wdbFiles:getModificationDate ( $collectionPath as xs:string, $fileName as xs:string ) as xs:dateTime {
+ let $dateTime := xmldb:last-modified($collectionPath, $fileName)
+ , $adjusted := adjust-dateTime-to-timezone($dateTime,"-PT0H0M")
+
+ return xs:dateTime(format-dateTime($adjusted, "[Y]-[M01]-[D01]T[H01]:[m]:[s]Z"))
+};
+
+declare function wdbFiles:evaluateIfModifiedSince ( $id as xs:string, $requestedModified as xs:string+ ) as xs:double {
+ let $path := wdbFiles:getFullPath($id)
+
+ return wdbFiles:evaluateIfModifiedSince($path?collectionPath, $path?fileName, $requestedModified)
+};
+
+(:~
+ : evaluate If-Modified-Since and return either 200 or 304
+ :)
+declare function wdbFiles:evaluateIfModifiedSince ( $collectionPath as xs:string, $fileName as xs:string, $requestedModified as xs:string+ ) as xs:double {
+ let $modifiedWithoutMillisecs := wdbFiles:getModificationDate($collectionPath, $fileName)
+ , $requestedModifiedParsed := parse-ietf-date(string-join($requestedModified))
+
+ return if ( $requestedModifiedParsed lt $modifiedWithoutMillisecs )
+ then 200
+ else 304
+};
+
+(:~
+ : format da given datetime as IETF date
+ :
+ : @param gmtDateTime an xs:dataTime adjust to GMT
+ : @returns xs:string formated as an IETF date
+ :)
+declare function wdbFiles:ietfDate ( $gmtDateTime as xs:dateTime ) as xs:string {
+ format-dateTime($gmtDateTime, "[FNn,3-3], [D00] [MNn,3-3] [Y] [H01]:[m]:[s] GMT")
+};
diff --git a/edoc/post-install.xql b/edoc/post-install.xql
index aad81d2f..8153df4d 100644
--- a/edoc/post-install.xql
+++ b/edoc/post-install.xql
@@ -2,7 +2,21 @@ xquery version "3.1";
let $targetCollection := '/db/apps/edoc'
-let $cp := xmldb:copy-collection($targetCollection || '/config/edoc', '/db/system/config/db/apps')
+(: let $cp := xmldb:copy-collection($targetCollection || '/config/edoc', '/db/system/config/db/apps') :)
+(: It seems that copying and then re-indexing does not suffice. A workaround reported in
+ : https://github.com/eXist-db/exist/issues/5099#issuecomment-1775120346 suggests that storing
+ : a collection.xconf might help. :)
+let $indexConfig := (
+ xmldb:create-collection("/db/system/config/db/apps", "edoc"),
+ xmldb:create-collection("/db/system/config/db/apps/edoc", "addins"),
+ xmldb:create-collection("/db/system/config/db/apps/edoc", "annotations"),
+ xmldb:create-collection("/db/system/config/db/apps/edoc", "data"),
+ xmldb:create-collection("/db/system/config/db/apps/edoc", "rest"),
+ xmldb:store("/db/system/config/db/apps/edoc/addins", "collection.xconf", doc($targetCollection || "/config/edoc/addins/collection.xconf")),
+ xmldb:store("/db/system/config/db/apps/edoc/annotations", "collection.xconf", doc($targetCollection || "/config/edoc/annotations/collection.xconf")),
+ xmldb:store("/db/system/config/db/apps/edoc/data", "collection.xconf", doc($targetCollection || "/config/edoc/data/collection.xconf")),
+ xmldb:store("/db/system/config/db/apps/edoc/rest", "collection.xconf", doc($targetCollection || "/config/edoc/rest/collection.xconf"))
+)
let $collsr := (
"/modules", "/templates", "/resources/css", "/resources/scripts", "/resources/xsl"
@@ -37,7 +51,8 @@ let $chmod := (
let $reindex := (
xmldb:reindex($targetCollection || '/data'),
xmldb:reindex($targetCollection || '/rest'),
- xmldb:reindex($targetCollection || '/annotation')
+ xmldb:reindex($targetCollection || '/annotation'),
+ xmldb:reindex($targetCollection || '/addins')
)
return ($reindex, $chmod)
\ No newline at end of file
diff --git a/edoc/resources/mets.xsl b/edoc/resources/mets.xsl
deleted file mode 100644
index 8472698f..00000000
--- a/edoc/resources/mets.xsl
+++ /dev/null
@@ -1,494 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Contents
-
-
- Inhalt
-
-
- Parallel Views
-
-
- Parallele Anzeige
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/edoc/resources/nav.xsl b/edoc/resources/nav.xsl
index 7550f1ca..5310527f 100644
--- a/edoc/resources/nav.xsl
+++ b/edoc/resources/nav.xsl
@@ -51,7 +51,7 @@
-
+ display: none;
diff --git a/edoc/resources/scripts/admin.js b/edoc/resources/scripts/admin.js
index a3db1a92..763ef34e 100644
--- a/edoc/resources/scripts/admin.js
+++ b/edoc/resources/scripts/admin.js
@@ -1,6 +1,3 @@
-/* globals wdb */
-/* jshint browser: true */
-/* globals wdb */
"use strict";
const wdbAdmin = {
@@ -111,9 +108,14 @@ const wdbAdmin = {
/* jshint loopfunc: true*/
reader.onload = async function ( readFile ) {
tableData.innerText = ".";
- let fileContent = readFile.target.result,
- parser = new DOMParser(),
- parsed;
+ let fileContent = readFile.target?.result;
+ if ( fileContent === undefined || fileContent === "" || fileContent === null ) {
+ wdb.report("error", "empty", "no file content", tableData);
+ return false;
+ }
+
+ let parser = new DOMParser()
+ , parsed;
// try to parse as XML (for now, we only handle XML files here)
try {
@@ -124,11 +126,16 @@ const wdbAdmin = {
}
// try to find an ID for the XML file
- let xml = $(parsed),
- fileID = xml.find("TEI").attr("xml:id");
+ let xml = $(parsed)
+ , fileID = xml.find("tei\\:TEI, TEI").attr("xml:id")
+ , parserError = xml.find("parsererror");
- if (fileID === undefined || fileID == "") {
- wdb.report("error", "no @xml:id found in " + file.name, {}, tableData);
+ if ( xml.find("parsererror").length > 0 ) {
+ wdb.report("error", "parser error", parserError.text(), tableData);
+ return false;
+ }
+ if ( fileID === undefined || fileID === "" ) {
+ wdb.report("error", "ID missing", "no @xml:id found in " + file.name, {}, tableData);
return false;
}
diff --git a/edoc/resources/scripts/search.js b/edoc/resources/scripts/search.js
index 1148a61b..63c834ba 100644
--- a/edoc/resources/scripts/search.js
+++ b/edoc/resources/scripts/search.js
@@ -2,7 +2,7 @@ $(() => {
$(document).on('click', '.loadSearchResult', ( event ) => {
let id = event.target.dataset.target
, q = event.target.dataset.query
- , p = JSON.parse(decodeURI(wdb.parameters.p));
+ , p = JSON.parse(decodeURIComponent(wdb.parameters.p));
if ( q !== undefined && p.job == 'fts' ) {
wdbDocument.loadContent(wdb.meta.rest + 'search/file/' + id + '.html?q=' + q, id, event.target);
diff --git a/edoc/resources/start.xsl b/edoc/resources/start.xsl
index c802e0bd..b8f7efea 100644
--- a/edoc/resources/start.xsl
+++ b/edoc/resources/start.xsl
@@ -1,10 +1,5 @@
-
-
-
+
+
@@ -109,14 +104,23 @@
+ Lizenzinformationen:
-
-
-
+
+
+
+
+
+
+
+
+
+
+ :
@@ -136,4 +140,4 @@
-
\ No newline at end of file
+
diff --git a/edoc/resources/xsl/tei-common.xsl b/edoc/resources/xsl/tei-common.xsl
index a1f1634c..7f1f38ae 100644
--- a/edoc/resources/xsl/tei-common.xsl
+++ b/edoc/resources/xsl/tei-common.xsl
@@ -677,7 +677,20 @@
+
+
+
+
+
+
+
+
+
+
+
-
+
diff --git a/edoc/resources/xsl/tei-index.xsl b/edoc/resources/xsl/tei-index.xsl
new file mode 100644
index 00000000..14fd3061
--- /dev/null
+++ b/edoc/resources/xsl/tei-index.xsl
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
diff --git a/edoc/resources/xsl/tei-introduction.xsl b/edoc/resources/xsl/tei-introduction.xsl
index c89ed43d..2b2bdb80 100644
--- a/edoc/resources/xsl/tei-introduction.xsl
+++ b/edoc/resources/xsl/tei-introduction.xsl
@@ -1,18 +1,21 @@
-
-
-
-
-
+
+
+
+
+
+
-
-
-
-
diff --git a/edoc/resources/xsl/tei-transcript.xsl b/edoc/resources/xsl/tei-transcript.xsl
index 5a0255d7..f43d5fe5 100644
--- a/edoc/resources/xsl/tei-transcript.xsl
+++ b/edoc/resources/xsl/tei-transcript.xsl
@@ -1,5 +1,5 @@
diff --git a/edoc/rest/common.xqm b/edoc/rest/common.xqm
index ff0c4ad3..9dc6c06e 100644
--- a/edoc/rest/common.xqm
+++ b/edoc/rest/common.xqm
@@ -52,6 +52,24 @@ declare function wdbRCo:evaluatePreflight ( $originHeader as xs:string, $method
};
+(:~
+ : Return a short answer to HTTP HEAD request with Last-Modified header
+ :)
+declare function wdbRCo:head ( $filePath as xs:string ) as element(rest:response) {
+ let $pathParts := tokenize(replace($filePath, '//', '/'), '/')
+ , $collection := string-join($pathParts[not(position() = last())], '/')
+ , $dateTime := xmldb:last-modified($collection, $pathParts[last()])
+ , $adjusted := adjust-dateTime-to-timezone($dateTime,"-PT0H0M")
+ , $last-modified := format-dateTime($adjusted, "[FNn,3-3], [D00] [MNn,3-3] [Y] [H01]:[m]:[s] GMT")
+
+ return
+
+
+
+
+
+};
+
(:~
: Get a project specific / instance specific / global XSLT by name
:
diff --git a/edoc/rest/rest-coll.xql b/edoc/rest/rest-coll.xql
index d0e1f2cf..46e81b55 100644
--- a/edoc/rest/rest-coll.xql
+++ b/edoc/rest/rest-coll.xql
@@ -2,16 +2,16 @@ xquery version "3.1";
module namespace wdbRc = "https://github.com/dariok/wdbplus/RestCollections";
-import module namespace wdb = "https://github.com/dariok/wdbplus/wdb" at "/db/apps/edoc/modules/app.xqm";
-import module namespace wdbErr = "https://github.com/dariok/wdbplus/errors" at "/db/apps/edoc/modules/error.xqm";
-import module namespace wdbfp = "https://github.com/dariok/wdbplus/functionpages" at "/db/apps/edoc/modules/function.xqm";
-import module namespace wdbRCo = "https://github.com/dariok/wdbplus/RestCommon" at "/db/apps/edoc/rest/common.xqm";
-import module namespace wdbRMi = "https://github.com/dariok/wdbplus/RestMIngest" at "/db/apps/edoc/rest/ingest.xqm";
-import module namespace xstring = "https://github.com/dariok/XStringUtils" at "/db/apps/edoc/include/xstring/string-pack.xql";
+import module namespace wdb = "https://github.com/dariok/wdbplus/wdb" at "/db/apps/edoc/modules/app.xqm";
+import module namespace wdbErr = "https://github.com/dariok/wdbplus/errors" at "/db/apps/edoc/modules/error.xqm";
+import module namespace wdbFiles = "https://github.com/dariok/wdbplus/files" at "/db/apps/edoc/modules/wdb-files.xqm";
+import module namespace wdbfp = "https://github.com/dariok/wdbplus/functionpages" at "/db/apps/edoc/modules/function.xqm";
+import module namespace wdbRCo = "https://github.com/dariok/wdbplus/RestCommon" at "/db/apps/edoc/rest/common.xqm";
+import module namespace wdbRMi = "https://github.com/dariok/wdbplus/RestMIngest" at "/db/apps/edoc/rest/ingest.xqm";
+import module namespace xstring = "https://github.com/dariok/XStringUtils" at "/db/apps/edoc/include/xstring/string-pack.xql";
declare namespace http = "http://expath.org/ns/http-client";
declare namespace meta = "https://github.com/dariok/wdbplus/wdbmeta";
-declare namespace mets = "http://www.loc.gov/METS/";
declare namespace output = "http://www.w3.org/2010/xslt-xquery-serialization";
declare namespace rest = "http://exquery.org/ns/restxq";
declare namespace tei = "http://www.tei-c.org/ns/1.0";
@@ -407,13 +407,13 @@ function wdbRc:getStructureJson ( $id ) {
(: navigation :)
declare
%rest:GET
- %rest:path("/edoc/collection/{$id}/nav.xml")
-function wdbRc:getCollectionNavXML ($id as xs:string) {
- let $md := collection($wdb:data)/id($id)[self::meta:projectMD]
- let $uri := base-uri($md)
- let $struct := $md/meta:struct
+ %rest:path("/edoc/collection/{$ed}/nav.xml")
+function wdbRc:getCollectionNavXML ( $ed as xs:string ) {
+ let $md := collection($wdb:data)/id($ed)[self::meta:projectMD]
+ , $uri := base-uri($md)
+ , $struct := $md/meta:struct
- let $content := {(
+ let $content := {(
$struct/@*,
$struct/*
)}
@@ -450,52 +450,65 @@ declare function wdbRc:imported ( $import, $child ) {
: @return HTML (should be a html:nav element)
:)
declare function wdbRc:getCollectionNavHTML ( $ed as xs:string ) {
- wdbRc:getCollectionNavHTML ( $ed, () )
+ wdbRc:getCollectionNavHTML ( $ed, (), '' )
};
declare
%rest:GET
%rest:path("/edoc/collection/{$ed}/nav.html")
-function wdbRc:getCollectionNavHTML ( $ed as xs:string, $externalModel as map(*)? ) {
+ %rest:header-param("If-Modified-Since", "{$modified}")
+function wdbRc:getCollectionNavHTML ( $ed as xs:string, $externalModel as map(*)?, $modified as xs:string* ) {
let $model := if ( exists($externalModel) ) then $externalModel else wdbfp:populateModel("", $ed, "", "")
- , $params :=
-
-
-
- , $attributes :=
-
-
-
-
- let $html := try {
- if( ends-with($model?infoFileLoc, 'wdbmeta.xml') )
- then
- let $struct := wdbRc:getCollectionNavXML($ed)
- , $xsl := if ( wdb:findProjectFunction($model, "wdbPF:getNavXSLT", 0) )
- then (wdb:getProjectFunction($model, "wdbPF:getNavXSLT", 0))($model)
- else if ( doc-available($model?pathToEd || '/resources/nav.xsl') )
- then xs:anyURI($model?pathToEd || '/resources/nav.xsl')
- else if ( doc-available($wdb:data || '/resources/nav.xsl') )
- then xs:anyURI($wdb:data || '/resources/nav.xsl')
- else xs:anyURI($wdb:edocBaseDB || '/resources/nav.xsl')
-
- return transform:transform($struct, doc($xsl), $params, $attributes, ())
- else
- transform:transform(doc($model?infoFileLoc), doc($model?pathToEd || '/mets.xsl'), $params)
- } catch * {
-
Error transforming meta data file {$model?infoFileLoc} to navigation HTML: {$err:description}
- }
-
- let $status := if ( $html[self::*:p] ) then '500' else '200'
-
- return (
+
+ return if ( $modified != '' and wdbFiles:evaluateIfModifiedSince($model?pathToEd, 'wdbmeta.xml', $modified) = 304 )
+ then
-
-
-
-
- ,
- $html
- )
+
+
+ else
+ let $params :=
+
+
+
+ , $attributes :=
+
+
+
+ , $modified := wdbFiles:getModificationDate($model?pathToEd, 'wdbmeta.xml') => wdbFiles:ietfDate()
+
+ let $html := try {
+ let $struct := wdbRc:getCollectionNavXML($ed)
+ , $xsl := if ( wdb:findProjectFunction($model, "wdbPF:getNavXSLT", 0) )
+ then (wdb:getProjectFunction($model, "wdbPF:getNavXSLT", 0))($model)
+ else if ( doc-available($model?pathToEd || '/resources/nav.xsl') )
+ then xs:anyURI($model?pathToEd || '/resources/nav.xsl')
+ else if ( doc-available($wdb:data || '/resources/nav.xsl') )
+ then xs:anyURI($wdb:data || '/resources/nav.xsl')
+ else xs:anyURI($wdb:edocBaseDB || '/resources/nav.xsl')
+
+ return transform:transform($struct, doc($xsl), $params, $attributes, ())
+ } catch * {
+
Error transforming meta data file {$model?infoFileLoc} to navigation HTML: {$err:description}
+ }
+
+ let $status := if ( $html[self::*:p] ) then '500' else '200'
+ , $headers := if ( $html[self::*:p] )
+ then
+
+ else (
+ ,
+
+ )
+
+ return (
+
+
+
+
+ { $headers }
+
+ ,
+ $html
+ )
};
declare function wdbRc:getGeneral ($id, $mt, $content) {
diff --git a/edoc/rest/rest-files.xql b/edoc/rest/rest-files.xql
index 0884bb41..a2458e63 100644
--- a/edoc/rest/rest-files.xql
+++ b/edoc/rest/rest-files.xql
@@ -2,12 +2,13 @@ xquery version "3.1";
module namespace wdbRf = "https://github.com/dariok/wdbplus/RestFiles";
-import module namespace console = "http://exist-db.org/xquery/console" at "java:org.exist.console.xquery.ConsoleModule";
-import module namespace json = "http://www.json.org";
-import module namespace wdb = "https://github.com/dariok/wdbplus/wdb" at "/db/apps/edoc/modules/app.xqm";
-import module namespace wdbRCo = "https://github.com/dariok/wdbplus/RestCommon" at "/db/apps/edoc/rest/common.xqm";
-import module namespace wdbRMi = "https://github.com/dariok/wdbplus/RestMIngest" at "/db/apps/edoc/rest/ingest.xqm";
-import module namespace xstring = "https://github.com/dariok/XStringUtils" at "/db/apps/edoc/include/xstring/string-pack.xql";
+import module namespace console = "http://exist-db.org/xquery/console" at "java:org.exist.console.xquery.ConsoleModule";
+import module namespace json = "http://www.json.org";
+import module namespace wdb = "https://github.com/dariok/wdbplus/wdb" at "/db/apps/edoc/modules/app.xqm";
+import module namespace wdbFiles = "https://github.com/dariok/wdbplus/files" at "/db/apps/edoc/modules/wdb-files.xqm";
+import module namespace wdbRCo = "https://github.com/dariok/wdbplus/RestCommon" at "/db/apps/edoc/rest/common.xqm";
+import module namespace wdbRMi = "https://github.com/dariok/wdbplus/RestMIngest" at "/db/apps/edoc/rest/ingest.xqm";
+import module namespace xstring = "https://github.com/dariok/XStringUtils" at "/db/apps/edoc/include/xstring/string-pack.xql";
declare namespace http = "http://expath.org/ns/http-client";
declare namespace meta = "https://github.com/dariok/wdbplus/wdbmeta";
@@ -61,6 +62,13 @@ function wdbRf:storeFilePreflight ( $id as xs:string, $origin as xs:string* ) as
wdbRCo:evaluatePreflight($origin, "PUT")
};
+declare
+ %rest:HEAD
+ %rest:path("/edoc/resource/{$id}")
+function wdbRf:fileHead ( $id as xs:string ) as element(rest:response) {
+ wdbRCo:head(wdb:getFilePath($id))
+};
+
(: upload a single file with known ID (i.e. one that is already present)
- if the ID is not found, return an error
- replace the file and update its meta:file
@@ -176,7 +184,8 @@ declare
%rest:GET
%output:indent("no")
%rest:path("/edoc/resource/{$id}")
-function wdbRf:getResource ($id as xs:string) {
+ %rest:header-param("If-Modified-Since", "{$modified}")
+function wdbRf:getResource ( $id as xs:string, $modified as xs:string* ) {
(: Admins are advised by the documentation they REALLY SHOULD NOT have more than one entry for every ID
: To be on the safe side, we go for the first one anyway :)
let $files := collection($wdb:data)//id($id)[self::meta:file]
@@ -211,6 +220,8 @@ function wdbRf:getResource ($id as xs:string) {
404
else if ( not($readable) ) then
401
+ else if ( count($doc) = 1 and $modified != "" ) then
+ wdbFiles:evaluateIfModifiedSince($id, $modified)
else if ( count($doc) = 1 ) then
200
else
@@ -237,6 +248,7 @@ function wdbRf:getResource ($id as xs:string) {
}
+
,
if ($respCode = 200)
@@ -379,23 +391,19 @@ declare
%rest:query-param("view", "{$view}", "")
function wdbRf:getResourceView ($id as xs:string, $type as xs:string, $view as xs:string*) {
let $model := wdb:populateModel($id, $view, map {})
-
- (: This mechanism can only be used with wdbmeta. A METS-only project will return an error :)
- let $wdbmeta := if (ends-with($model?infoFileLoc, "wdbmeta.xml"))
- then doc($model?infoFileLoc)
- else ()
+ , $wdbmeta := doc($model?infoFileLoc)
(: by definition in wdbmeta.rng and in analogy to the behaviour of view.html: $type maps to process/@target,
$view is used as a parameter. If there is only one process for $type, $view will be handed over as a parameter;
if there are multiple processes for $type, $view will be used to select via process/@view. If the are multiple
processes but none with the given $view, this is an error :)
let $processes := $wdbmeta//meta:process[@target = $type]
- let $process := if (count($processes) = 1)
- then ($processes[1])
- else ($processes[@view = $view])
+ let $process := if ( count($processes) = 1 )
+ then $processes[1]
+ else $processes[@view = $view]
- let $status := if ($wdbmeta = ())
- then (500, "no wdbmeta found for " || $id || " (project with mets.xml?)")
+ let $status := if ( $wdbmeta = () )
+ then (500, "no wdbmeta found for " || $id || "!")
else if (not($processes))
then (404, "no process found for target type " || $type)
else if (not($process))
@@ -477,7 +485,7 @@ declare function wdbRf:processXQuery($id as xs:string, $process as element(), $m
declare
%private
function wdbRf:image ($fileID as xs:string, $image as xs:string, $map as map(*)) {
- let $retrFile := wdbRf:getResource($fileID)
+ let $retrFile := wdbRf:getResource($fileID, "")
let $errorFile := if ($retrFile//http:response/@status != 200)
then "File not found or other error: " || $retrFile//http:response/@status
else ()
@@ -561,7 +569,7 @@ declare
%rest:path("/edoc/resource/iiif/{$id}/images")
%output:method("json")
function wdbRf:getImages($id as xs:string) {
- let $retrFile := wdbRf:getResource($id)
+ let $retrFile := wdbRf:getResource($id, "")
let $errorFile := if ($retrFile//http:response/@status != 200)
then "File not found or other error: " || $retrFile//http:response/@status
else ()
@@ -588,7 +596,7 @@ declare
%rest:path("/edoc/resource/iiif/{$id}/{$image}.json")
%output:method("json")
function wdbRf:getImageDesc($id as xs:string, $image as xs:string) {
- let $retrFile := wdbRf:getResource($id)
+ let $retrFile := wdbRf:getResource($id, "")
let $errorFile := if ($retrFile//http:response/@status != 200)
then "File not found or other error: " || $retrFile//http:response/@status
else ()
@@ -621,7 +629,7 @@ declare
%rest:path("/edoc/resource/iiif/{$id}/manifest.json")
%output:method("json")
function wdbRf:getFileManifest ($id as xs:string) {
- let $retrFile := wdbRf:getResource($id)
+ let $retrFile := wdbRf:getResource($id, "")
let $errorFile := if ($retrFile//http:response/@status != 200)
then "File not found or other error: " || $retrFile//http:response/@status
else ()
diff --git a/test/entities.http b/test/entities.http
index 8ed3a825..b16d5d86 100644
--- a/test/entities.http
+++ b/test/entities.http
@@ -3,8 +3,18 @@ GET https://exist.ulb.tu-darmstadt.de/2/r/edoc/entities/list/file/pa000008-0130/
###
-GET https://exist.ulb.tu-darmstadt.de/2/r/edoc/collection/pa000015
-Accept: application/xml
+GET https://tueditions.ulb.tu-darmstadt.de/r/edoc/collection/pa000018
+Accept: application/json
+
+###
+
+GET https://tueditions.ulb.tu-darmstadt.de/r/edoc/resource/pa000018-0001
+#If-Modified-Since: Thu, 15 Feb 2024 18:14:21 GMT
+
+###
+
+GET https://tueditions.ulb.tu-darmstadt.de/v/pa000018-0001
+If-Modified-Since: Thu, 15 Feb 2024 18:14:21 GMT
###
@@ -26,3 +36,7 @@ https://exist.ulb.tu-darmstadt.de/1/r/edoc/entities/pd000090/org/byId?q=https%3A
GET https://tueditions.ulb.tu-darmstadt.de/v/pd000090/per/np000012
+###
+
+GET https://exist.ulb.tu-darmstadt.de/1/r/edoc/collection/pa000018/nav.html?html
+If-Modified-Since: Fri, 23 Feb 2024 19:42:00 GMT
\ No newline at end of file