\documentclass[english,a4paper,11pt]{article}
\usepackage[english]{babel}
\usepackage{colortbl}
\usepackage{xcolor}
\usepackage{fancyhdr}
\usepackage{listings}
\usepackage{graphicx}
\usepackage{mdframed}
\usepackage[export]{adjustbox}
\usepackage{hyperref}
\usepackage{longtable}
\usepackage{tabu}
\pagestyle{fancy}
\definecolor{myblue}{rgb}{0,0.1,0.6}
\definecolor{mygray}{rgb}{0.5,0.5,0.5}
\definecolor{mymauve}{rgb}{0.58,0,0.82}
\lstset{
basicstyle=\small\ttfamily,
columns=flexible,
keepspaces=true,
breaklines=true,
keywordstyle=\color{myblue}
}
\lstloadlanguages{xml}
\def\Gin@extensions{.pdf,.png,.jpg,.mps,.tif}
\graphicspath{{//data//doc/}}

\catcode`|=4
% set left and right margin
\newenvironment{changemargin}[2]{%
\begin{list}{}{%
\setlength{\topsep}{0pt}%
\setlength{\leftmargin}{#1}%
\setlength{\rightmargin}{#2}%
\setlength{\listparindent}{\parindent}%
\setlength{\itemindent}{\parindent}%
\setlength{\parsep}{\parskip}%
}%
\item[]}{\end{list}}
\def\signed #1{{\leavevmode\unskip\nobreak\hfil\penalty50\hskip2em
\hbox{}\nobreak\hfil#1%
\parfillskip=0pt \finalhyphendemerits=0 \endgraf}}
\newsavebox\mybox
\newenvironment{aquote}[1]
{\savebox\mybox{#1}\begin{quote}}
{\signed{\usebox\mybox}\end{quote}}

% Styles

\newcommand{\TeiEmphasisI}[1]{\textit{#1}}

\newcommand{\TeiTdI}[1]{\textbf{#1}}

\newcommand{\TeiEmphasisII}[1]{\textit{#1}}

\newcommand{\TeiGuilabel}[1]{\textit{#1}}

\begin{document}

\title{TEI Publisher Documentation} \author{}
\maketitle

\section*{Introduction}\markboth{Introduction}{Introduction}

\label{introduction}

\subsection*{What TEI Publisher does ...}

\label{introduction-explainer}
The motivation behind TEI Publisher was to provide a tool which enables scholars and
editors to publish their materials without becoming programmers, but also does not force
them into a one-size-fits-all framework. Experienced developers will benefit as well by
writing less code, avoiding redundancy, improve maintenance and interoperability - to just
name a few. TEI Publisher is all about \TeiEmphasisI{standards}, \TeiEmphasisI{modularity}, \TeiEmphasisI{reusability} and
\TeiEmphasisI{sustainability}! 

In Publisher, it all starts with your source documents - regardless if they are in TEI
or other form of XML: DocBook, MS Word (DOCX) or JATS. No matter how the source material has
been encoded, it can be easily transformed into a range of output formats for publication -
from a modern web page that you can open on your laptop or mobile device, to an ebook, a PDF
file or its LaTeX source.

TEI Publisher derives its name from TEI and the TEI Processing Model (PM). Processing
Model is a part of the TEI vocabulary and TEI ODD specification format, described in the
\href{http://www.tei-c.org/release/doc/tei-p5-doc/en/html/TD.html#TDPM}{TEI P5
guidelines} as well as further chapters here. It defines how a TEI document should
be rendered in different output formats and lies at the heart of TEI Publisher. 

However, online editions require more than just a text transformation: the text needs to
be embedded into an application context, adding navigation, pagination, search, facsimile
display and so on. The larger part of TEI Publisher deals with those aspects, providing all
the necessary building blocks for an online edition.

Staying true to the spirit of code reuse and interoperability, TEI Publisher implements
its functionalities as small "lego" blocks to be freely arranged and recombined. The
technology making this possible is called \TeiEmphasisII{Web Components}. It is part of
the HTML5 specification and natively implemented by many browsers. Users don't need to dive
into the details of this standard though: all you need to modify the example pages is some
basic HTML knowledge. 

Only where the \href{https://cdn.tei-publisher.com/api.html}{available components} are not
enough, a new use case needs to be described and suitable new components implemented but
then they can be incorporated into existing component pool for everyone else to use. After
all, our mantra is reuse, reuse, reuse and we want to turn TEI Publisher into a box of tools
the entire community can benefit from. 

Despite the elegant simplicity of this approach, various projects we realized in the
past prove that TEI Publisher is:

\begin{enumerate}
\item {
powerful enough to cover complex transformation needs

}\item {
a truly universal tool for any kind of digital edition

}\item {
capable of generating high quality, camera ready material for book publishing

}\item {
sustainable and future-proof solution

}\item {
suitable for any XML, not just TEI (this documentation is written in
DocBook!)

}\end{enumerate}

As the project matured, it became very clear that, apart from publishing the 
XML sources curated through other tools and platforms, our user community is desperately wishing for some aids to 
convert and incorporate data from other formats as well as to enrich and annotate documents, ideally without angle brackets in sight.
Answering these needs, first the capacity to handle Word DOCX and Markdown, and later a user friendly 
annotation editor have been added as described in relevant sections.

\subsection*{e-editiones.org}

\label{e-editiones}
Since its first incarnation in 2015, TEI Publisher has gained substantial following
with numerous academic and commercial projects around the globe using it for their editorial
and publishing needs. Grass-roots user initiative led in 2020 to the foundation of an
international non-profit association \href{https://e-editiones.org}{e-editiones.org} with the focus on further
joint development of TEI Publisher, open standards and best practices for digital editions. 

TEI Publisher development is only possible thanks to generous contributions of
developers, users and institutions willing to employ Open Source approaches so that the
whole community can reuse and benefit from their work.

A growing number of projects from small to large that have decided to publish their
materials with TEI Publisher gives us all not only the opportunity but also the
responsibility to make the project thrive for years to come and to make it truly sustainable
option for XML publishing! Consider joining \href{https://e-editiones.org}{e-editiones.org} through your affiliated
institution or individually to support our efforts. 

We invite the community to contribute to the project - by means of code, ideas,
documentation, tutorials and funding. 

You don't have to be a developer to contribute, you can do so in a number of ways! 

\begin{enumerate}
\item {
Check out the source code, modify it, document it, enhance it.

}\item {
Create new or enhance existing example documents and ODDs so we present showcases
for various TEI applications.

}\item {
Report your issues, feature requests or ideas for discussion via \href{https://github.com/eeditiones/tei-publisher-app/issues}{GitHub issue tracker}. 

}\item {
Discuss with us on \href{https://join.slack.com/t/e-editiones/shared_invite/zt-e19jc03q-OFaVni~_lh6emSHen6pswg}{e-editiones slack chat} or through the \href{https://admin.hostpoint.ch/mailman/listinfo/community_e-editiones.org}{mailing list} and \href{https://twitter.com/EEditiones}{@EEditiones twitter}. 

}\item {
Contribute to translations via \href{https://crwd.in/tei-publisher}{Crowdin}. Please contact us if your
target language is not listed and you'd like to work on it. 

}\item {
Port back your custimizations to the TEI Publisher code base so that others can use
it too (or ask us to do it for you)! 

}\item {
Help and mentor others - publish teaching materials, answer questions on our Slack
channel, mailing list and other forums. 

}\item {
Sponsor a concrete feature or fund a development grant. 

}\end{enumerate}

\subsection*{Versions}

\label{versions}
TEI Publisher has been under active development since 2015. Once or twice a year a new
major version is released, bringing important new features.

Minor versions are released at shorter intervals and offer bug fixes, minor new features
and improvements.

The current major version of the TEI Publisher is 9.0.0

There's a long list of ideas and features we'd like to see incorporated into TEI
Publisher: from wider coverage of input and output formats (e.g. InDesign), CQL and DTS
support, to various editing workflows and support for efficient hosting and maintenance of
multiple editions. These ideas are in various stages of development - some already advanced,
some in conceptual phase, some waiting for funding and implementation. Coordination of
future work is primarily conducted by \href{https://e-editiones.org}{e-editiones.org}. 

\begin{figure}[h]
\caption{Image by \href{https://pixabay.com/users/mabelamber-1377835}{Mabel Amber} from \href{https://pixabay.com}{Pixabay}
}

\includegraphics[max size={\textwidth}{\textheight}]{nine-3095449_640.jpg}

\end{figure}

\subsubsection*{What's new in TEI Publisher 9.0.0}

\label{v9}
Version 9 has seen a major rework of the annotation facilities and introduced local authority registers for people, places and organizations.
There have been small but powerful improvements to facets and numerous minor fixes and extensions, including redesign of the layout templates and ODDs
for some of the examples from the Demo Collection.

As showcased in the \href{../test/F-rom.xml}{Shakespeare sample} and app, TEI Publisher now supports generating IIIF presentation manifests and displaying them alongside
the text. Text and image view communicate to each other, which means that if you navigate to the next page/image in either of the two, the other
reacts accordingly. While there are external tools for creating IIIF manifests, the Shakespeare sample auto-generates them from the TEI header and the
page breaks in the document.

The URL routing features introduced with version 8 have been substantially improved, introducing configurable URL templates also on the client
side. This means you can construct URLs which are really completely independent of the underlying data organisation, while making sure the user always
sees the page in a consistent state.

Furthermore it became easier to select less frequent facets when browsing or searching: previously only the most frequent facets where shown by
default and you had to browse through a potentially long list if you wanted to find a not so common one. Now you can display a combo box in addition
to the list, allowing users to type in a string and see matching facets.

This edition has also brought the demise of the \texttt{teiSimplePrint} ODD, previously the source ODD for the \texttt{teipublisher}
ODD. Models from the SimplePrint, after thorough review, have been merged into the default TEI Publisher ODD. This is a first step on the road for the
extended and rationalized base ODD, a project inspired by the TEI Vanilla meetups of yore and now undertaken by e-editiones in cooperation with the
TEI consortium.

The new annotation editor boasts a new, more user friendly and ergonomic layout with additional 
capacity to add or edit registry entries from within the editor. Furthermore, a function to find potential matches for 
the current annotation and review them on the spot is the long awaited feature, which promises to speed up the editing process without 
compromising quality or consistency.

A default set up for local registers of places, people and organizations allows editors to curate these resources under the same 
roof and at the same time as they annotate the sources. As usual, our registers provide a firm base for extensions and customizations.

Since the release of the previous version there was a new major version of the \texttt{tei-publisher-lib} and numerous releases of TEI
Publisher's \texttt{webcomponents} library.

See chapter on Updating for information how to update
your app to the newest version.

\subsubsection*{What's new in TEI Publisher 8.0.0}

\label{v8}
Version 8 has been focused on a major rework of the URL handling and redesign of
search facilities. A number of further examples gives a better idea of the projects
already using TEI Publisher for their editions. There have also been significant changes
to connected resources: the tei-publisher-lib, webcomponents library and roaster.

See chapter on Updating for information how to update
your app to the newest version.

\subsubsection*{What's new in TEI Publisher 7.0.0}

\label{v7}
Version 7 brought another major refactoring and restructuring of TEI Publisher app,
particularly regarding the server-side modules.

TEI Publisher now exposes a well-defined, clear \href{../api.html}{API specification} following the \href{http://spec.openapis.org/oas/v3.0.3}{Open API standard}. This API is
used in TEI Publisher by client-side UI components but can be equally well utilized by
independent software which harnesses functionality exposed via the API without being
forced to rely on Publisher's client-side components. 

On the server a new package, oas-router, reads the API
specification and uses it to map HTTP requests to XQuery functions which perform actual
API operations. Other packages, particularly UI web components (
pb-components) and TEI Processing Model library (
tei-publisher-lib) underwent necessary changes to communicate with
the new API as well as retain full backwards compatibility. 

Beyond the structural changes a number of reported issues has been fixed and broader
test coverage for all packages introduced. A sophisticated CI setup based on Docker has
been created. Extensive test suite has been prepared for individual components.
Furthermore, every API operation is independently tested against the specification, to
assure that e.g. parameter and response types correspond exactly to the definition.

Thanks to community contributions via \href{https://crwd.in/tei-publisher}{Crowdin}, TEI Publisher is now
available in 20 languages. 

See chapter on Updating for information how to update
your app to take advantage of these developments. 

\subsubsection*{What's new in TEI Publisher 6.0.0}

\label{v6}
Version 6 brought a major refactoring and restructuring of TEI Publisher app libraries
along with new specialized components and use case examples.

\begin{enumerate}
\item {
Web components overhaul: migration to \href{https://lit-element.polymer-project.org/}{LitElement} and to the
npm library 

While invisible to users, this redesign greatly improves the modularity of
Publisher-based applications. With Publisher web component releases published on npm,
updating the user interface for all Publisher-based apps is just a question of
changing a single variable in the configuration file.

Furthermore, Publisher's library of web components - true to the basic idea of
\href{https://developer.mozilla.org/en-US/docs/Web/Web_Components}{Web
Components Standard} can be included in any HTML webpage e.g. can be embedded
into existing CMS or any other publishing solution, even if it's not running eXist-db. 

Similarly, if you prefer to write your own application using any of the popular
frameworks like \TeiEmphasisII{angular, vue or react} you can easily import the
\texttt{ pb-components} package from npm and use it directly in your project. 

As a final consequence, this change decouples the component library from the TEI
Publisher app. It is now possible to host multiple applications, which depend on
different versions of the component library, without conflict within the same eXist-db
instance, a point of importance for institutions with numerous projects.

}\item {
Redesigned and simplified CSS styling customization

Encapsulation of styles offered by web components can be a mixed blessing and
poses some challenges when customizing the aesthetics of components to fit a project.
While some aspects of component styling remained unaccessible for customization in
previous versions, Publisher 6 exposes majority of styling properties via standard CSS
files and theme variables. Stylesheets can also be specified within the ODD, as
previously, or through \texttt{pb-view} component configuration attributes.

}\item {
Extended internationalization

I18n support has been extended to cover not only the labels in HTML templates but
also within web components. A mechanism for project specific language files extending
the default Publisher label collection has been added.

Thanks to community contributions via \href{https://crwd.in/tei-publisher}{Crowdin} a number of new languages
has been added and existing ones updated. 

}\item {
Subcorpora - new TEI Publisher data organization

Publisher's pre-populated data collection is now split into
\TeiEmphasisII{Playground} and \TeiEmphasisII{TEI Publisher demo
collection} areas which illustrate how this mechanism could be used to
host multiple subcorpora within single TEI Publisher application. 

}\item {
New and improved web components

\texttt{pb-select-feature} and \texttt{pb-toggle-feature} components have been
extended to allow for interactive changing of display parameters (like switching
between regularized or original spelling) which can be then processed client or
server-side. 

New components have been created to handle MEI music notation as well as for web
component API documentation and demo pages.

}\item {
User interface of the ODD editor has been improved.

}\item {
Experimental incremental scroll mode has been introduced to improve performance
for very long documents presented in single page mode.

}\end{enumerate}

\section*{Quickstart}\markboth{Quickstart}{Quickstart}

\label{quickstart}

\subsection*{«Stay Home Learn TEI Publisher From Scratch»}

\label{workshop-2020}
A 3-part online course has been organized by e-editiones and led by Wolfgang Meier in
June 2020. Course material, as well as video recordings of all the sessions, and a
walk-through for the assignments are available for self-study. Find all informations on the
\href{https://github.com/eeditiones/workshop#slides}{workshop
GitHub} page. 

\begin{center}
Not available in PDF edition. Go to \url{https://www.youtube-nocookie.com/embed/QuWrfAS2SWM} to view.
\end{center}

\subsection*{Installation}

\label{installation}
TEI Publisher requires the \href{http://exist-db.org}{eXist XML database} to operate. It is distributed as an eXist application package,
making it easy to install on any eXist database instance - either on your local machine or
any remote server. 

You can install eXist and TEI Publisher manually, as described below. Alternatively use
the provided docker image. 

\subsubsection*{Installing into an eXist instance}

\label{exist-installation}

\paragraph*{Java}

\label{java}
Before installing eXist, make sure you have Java installed on your machine. You can
run java -version on a command line to check which version of Java
you have. Make sure you have at least Java 8 (recommended: Java 11). Please note that
the java -version shows the full version string, so 1.8.0 or similar
instead of just 8. 

If you do not have Java installed, you can choose between a variety of different
Java distributions for your operating system. While these are largely equivalent, so far
we have had the smoothest installation experience across operating systems with the
\href{https://www.azul.com/downloads/zulu-community/?package=jdk}{Zulu Community
OpenJDK} builds. In particular for Windows users, this provides the best out of
the box experience. 

\paragraph*{Download}

\label{download}

Download an eXist distribution following the link on its \href{http://exist-db.org/exist/apps/homepage/index.html#downloads}{homepage}. 

\begin{mdframed}[frametitle={}]
It is recommended that you set up an admin password when installing eXist but make
sure to remember or store it securely!

\end{mdframed}

\paragraph*{Mac installation}

\label{mac-installation}
On a Mac download the file with the .dmg extension, e.g. "
eXist-db-5.x.x.dmg ". 

Double clicking the downloaded .dmg file should install eXist on
your local system. It is only required to drag the eXist app icon over to the
Applications folder. 

Once the installation has completed, you should find an app in your Applications
folder which you can use to launch eXist.

\paragraph*{Windows installation}

\label{windows-installation}
On Windows download the file with the .jar extension, e.g. "
exist-installer-5.x.x.jar ". 

Double clicking the .jar should install eXist on your local
system. It will launch an installer to guide you through basic settings. The default
settings suggested by the installer provide a good starting point for most projects. 

\begin{mdframed}[frametitle={}]
If double-clicking the .jar does not have any effect, there's
may be something wrong with your Java setup. The java binary
needs to be in your \%PATH\% environment. 

You can also try to manually start the installer by opening a command prompt,
changing to the directory where you downloaded the distribution and typing:

\begin{lstlisting}
java -jar exist-installer-5.x.x.jar
\end{lstlisting} 
\end{mdframed}

Once the installation is completed, you should find an eXist-db shortcut to launch
eXist.

\paragraph*{Unix installation}

\label{unix-installation}
Download the file with the .jar extension, e.g. " 
exist-installer-5.x.x.jar ". 

Double clicking the .jar should install eXist on your local
system. It will launch an installer to guide you through basic settings. Default
settings suggested by the installer provide a good starting point for most projects so
there's no need to change anything. 

Once the installation is completed, you should find an eXist-db shortcut to launch
eXist, otherwise navigate to the installation directory and run
bin/startup.sh. 

\begin{mdframed}[frametitle={}]
Some \TeiEmphasisII{Linux users} may prefer the plain
.tar.bz2 package, which can just be untarred to any location.
This package does not include an installer and eXist has to be launched on the command
line: navigate into the untarred directory and run 

\begin{lstlisting}
bin/startup.sh
\end{lstlisting}  in a shell, skipping the jar installer step above. Ignore the next section,
navigate directly to \href{http://localhost:8080}{
http://localhost:8080} and follow the steps for installing TEI Publisher via
the dashboard described further below. 

\end{mdframed}

\paragraph*{First launch}

\label{first-launch}
Once eXist is launched for the first time you should see (with the exception of some
Unix system configurations described above) a splash window popping up, showing that
default applications are being installed:

\begin{figure}[h]
\caption{Splash Screen on eXist Startup}

\includegraphics[max size={\textwidth}{\textheight}]{eXistSplash.png}

\end{figure}

Upon first start, an additional configuration window will pop up on Windows and Mac,
allowing you to configure basic parameters. Default settings suggested provide a good
starting point for most projects so usually there's no need to change anything. 

\begin{figure}[h]
\caption{Configuration Dialog Showing on First Start}

\includegraphics[max size={\textwidth}{\textheight}]{eXistInitialConfig.png}

\end{figure}

Clicking on Save will show a popup asking to confirm the
location of the data directory. Unless you have specific requirements just agree to the
suggestion of the configuration dialog. 

\TeiEmphasisII{Windows users} will be asked if they would like to install eXist as
a service. This is highly recommended to ensure that the database is correctly closed
whenever the operating system shuts down. 

If all went well, eXist should now be up and running in the background. Mac and
Windows users should find a small eXist icon in their task bar. Right-clicking on it
will reveal a menu:

\begin{figure}[h]
\caption{Taskbar Launcher Context Menu}

\includegraphics[max size={\textwidth}{\textheight}]{eXistTaskbarIcon.png}

\end{figure}

\paragraph*{Installing TEI Publisher}

\label{packageManager}
Clicking on Open Dashboard in the taskbar will open a
browser and display eXist's Dashboard: the central administrative hub for the database.
Alternatively - e.g. when you chose the manual installation on Linux - you can also open
a browser window and navigate to: \url{http://localhost:8080}. 

Log into the dashboard using the admin account and the password you chose during
the installation (it will be empty by default). Use the left sidebar to navigate to the
Package Manager. You'll see two tabs: the first one lists
the application packages currently installed, the second can be used to install
additional packages from eXist's public application repository. 

Switch to the Available tab and search the list for TEI
Publisher. Once you find it, click on the little install icon. 

After installing you will find the TEI Publisher icon in the tab showing installed
apps. Click on it to open the TEI Publisher.

\begin{figure}[h]
\caption{ Installing \TeiEmphasisII{TEI Publisher} from the Package Manager }

\includegraphics[max size={\textwidth}{\textheight}]{eXistDashboard.png}

\end{figure}

\subsubsection*{Using docker}

\label{docker}
If you do not want to install eXist yourself, you can use docker to run TEI
Publisher. Docker is a tool to simplify the installation of applications and services. It
creates a virtual environment including everything required for the service to run. Using
our \href{https://hub.docker.com/r/existdb/teipublisher}{docker image}, eXist will already be set up to include TEI Publisher as well as
the Shakespeare and Van Gogh demo apps. 

\begin{enumerate}
\item {
Install \href{https://www.docker.com/}{docker}
on your machine. Windows and Mac users may download the \href{https://www.docker.com/products/docker-desktop}{docker desktop}
app. 

}\item {
To download the image run the following in a console

\begin{lstlisting}
docker pull existdb/teipublisher:latest
\end{lstlisting} 

}\item {
once the download is complete, you can run the image with the following
command:

\begin{lstlisting}
docker run -p 8081:8080 -p 8444:8443 --name teipublisher existdb/teipublisher:latest
\end{lstlisting} 
Startup should be fast because the database is already pre-populated. However,
changes you make may not persist if the docker container is deleted or updated to a
newer release. If you want to be sure that your changes are safe, you should specify a
local volume for storing the database by adding:

\begin{lstlisting}
-v exist-data:/exist/data
\end{lstlisting} 
See below for an explanation of the parameters:

\begin{description}
\item [-p] 
Maps a port on your local machine (8081 and 8444) to the port used by eXist
within the container. eXist will always run on 8080 for HTTP and 8443 for HTTPS.
If those ports are already occupied by different services on your machine,
choose a different port for the first number.

\item [-v] 
Creates a named ("exist-data") volume for storing the database, using the
directory specified after the colon. If you skip this, any changes to the
database will be lost if you remove the docker container, update it or create a
new one. With -v the data will be stored outside the container. 

If you just intend to play around a bit, you can skip the parameter.

\item [--name] 
Assigns a name to the container, so you can reference it in other docker
commands, like \texttt{docker stop}. We'll use the name in all commands
below. 

\end{description}
Once the container has started, you can access the eXist dashboard in your browser
by navigating to

\begin{lstlisting}
http://localhost:8081
\end{lstlisting} 
From the dashboard you can click on the TEI Publisher, Shakespeare or Van Gogh
icons to open the corresponding applications.

}\item {
To stop the container run

\begin{lstlisting}
docker stop teipublisher
\end{lstlisting} 

}\item {
To start the container again:

\begin{lstlisting}
docker start teipublisher
\end{lstlisting} 
Note that when you restart a container, it will run in detached mode, so you won't
see any console output. You can view the output with following command though:

\begin{lstlisting}
docker logs teipublisher
\end{lstlisting} 

}\end{enumerate}

\paragraph*{Other useful commands}

\label{docker-other}
\begin{description}
\item [docker container ps -a] 
Lists all running and stopped containers

\item [docker volume ls] 
Displays existing volumes (where your database is stored)

\item [docker cp teipublisher:/exist-data .] 
Copy the contents of the database data volume to the current directory on
local disk, so you can back it up. Note that this will copy the raw database files
as created by eXist (not your XML, which is binary encoded inside those files).
Also make sure you run the command after stopping the active container.

\item [docker volume rm exist-data] 
Remove the contents of the database data volume (in case you would like to
start from scratch, deleting all changes you made).

\end{description}

Have a look at the docker documentation and \href{https://www.docker.com/sites/default/files/Docker_CheatSheet_08.09.2016_0.pdf}{ cheatsheet} for more commands. 

\subsection*{Browsing Documents}

\label{browsing}

\subsubsection*{The Start Page}

\label{start-page}
The start page of TEI Publisher serves as an entry point to explore and
experiment.

On a newly installed TEI Publisher the main application panel offers the choice
between browsing local collections directly or using DTS API to access remote resources.
Left side panel presents search and filtering options. Another panel to the right displays
the list of ODD files provided with the TEI Publisher.

\begin{figure}[h]
\caption{First options in the start page collection listing}

\includegraphics[max size={\textwidth}{\textheight}]{start-page-collections.png}

\end{figure}

The usual starting point is the \TeiEmphasisI{TEI Publisher Demo
Collection} with which users can explore a range of selected use cases, demonstrating various genres,
encoding styles and presentation layouts. Various customization aspects are handled using
different ODDs and view templates. We suggest to have a look at each of them to see what
TEI Publisher can achieve out of the box. 

\begin{mdframed}[frametitle={\paragraph*{Note}

}]
Documents in this collection are preinstalled with the TEI Publisher and users are
not allowed to write to it by default.

\end{mdframed}

The \TeiEmphasisI{Playground} collection is the place to upload
encoded documents and ODD files to experiment with various processing models and view
templates. 

Unlike the Demo collection, the Playground features an upload box to import new
documents. You can upload your own XML and ODD (e.g. TEI, DocBook or DOCX) documents by
either clicking on the \texttt{Upload} button or dragging and dropping files onto the
upload panel. Read more on this subject in the Upload
section. 

\begin{mdframed}[frametitle={\paragraph*{Note}

}]
You need to be \TeiEmphasisI{logged in} for most advanced actions
like creating or editing ODDs. The login button to the right of the menu bar allows you
to log in. By default, there's a user named tei-demo with
password demo, and a user tei with
password simple. 

\end{mdframed}
You will find other collections lower down, each showcasing a different encoding
scheme, like JATS or Markdown or a special use case scenario, like Annotations.

\subsubsection*{TEI Publisher Demo collection}

\label{demo-collection}
Experiment with browsing, faceting, filtering and sorting features of TEI Publisher.
This page consists of several main areas: \begin{enumerate}
\item {
the facets panel

}\item {
the list of documents currently installed with sorting and filtering
controls

}\item {
a panel showing the ODD files known to the application

}\item {
an upload box to upload new documents

}\end{enumerate}

Have a look at documents showcased here to get a sense of possibilities that TEI
Publisher offers. Click on document title to proceed to the Document View

\begin{figure}[h]
\caption{Browsing Demo collection}

\includegraphics[max size={\textwidth}{\textheight}]{demo-collection-overview.png}

\end{figure}

\subsection*{Selected Use Cases}

\label{selected-use-cases}
The document view can vary, sometimes substantially, depending on the sample document
you are looking at. This is a natural consequence of TEI's versatility and broad scope of
its application. What follows, requirements for the document view - both its layout and
composition as well as processing rules governing the transformation of the text of the
document itself - will differ to a great extent. Sample documents which are included in TEI
Publisher's installation package do not exhaust its applications but rather aim to present
some chosen use cases:

\begin{itemize}
\item {

\TeiEmphasisII{Critik der reinen Vernunft} from the \TeiEmphasisII{Deutsches
Textarchiv} corpus presents a philosophical tractate, originally published
in print, thus following 'traditional' book structure with front pages, foreword and
chapters. It can nevertheless demonstrate very well Publisher's capacities in
typesetting, switching between physical and logical structure of the document (just
toggle Page View in the Settings panel) as
well as generation of multiple output formats from single set of processing models in
the ODD (try choosing PDF or ePub options
in the Download). \TeiEmphasisII{Purchas his pilgrimages},
from the \TeiEmphasisII{EEBO-TCP} project, while roughly similar in structure is
much earlier work (1613) and demonstrates extensive use of marginal notes. 

}\item {
Shakespeare's \TeiEmphasisII{Romeo and Juliet}, from \TeiEmphasisII{Bodleian First
Folio} project uses dedicated TEI elements to encode structure of the play
but it also showcases the parallel transcription and facsimile alignment for its
presentation which is obviously of general application and could be used for any genre,
not limited to dramatic texts. 

}\item {
Correspondence corpora are common, yet very interesting, subjects for digital
editions. Despite basic similarities in structure, depending on the period, scope and
particular research perspective, intended presentation may vary enormously. We are
presenting samples of:

\begin{itemize}
\item {
A 15th century manuscript letter to \TeiEmphasisI{Mikołaj
Orlik} demonstrating alignment between Latin original and parallel
Polish translation.

}\item {
A 16th century manuscript letter of \TeiEmphasisI{Hernán
Cortés} showcasing parallel transcription/translation and facsimile view
and transcription enhanced with commentaries and explicitly encoded transcriptional
features.

}\item {
A 16th century manuscript letter of \TeiEmphasisI{Mauritius
Ferber} with a collapsible metadata panel in addition to the parallel
transcription and facsimile view.

}\item {
An early 19th century letter of a Polish historian \TeiEmphasisI{Joachim Lelewel} to his brother showcases possibly the simplest way of
encoding and displaying facsimiles: with complete URLs given in
\texttt{pb/@facs} attribute. It also demonstrates how TEI encoding of
hyphenated words could be processed for display in diplomatic vs normalized
view.

}\item {
A letter from \TeiEmphasisI{Van Gogh} to Paul Gauguin written
in 1888. This intentionally reproduces the flexible column layout pioneered by the
\href{http://vangoghletters.org}{Vincent Van Gogh
Letters} online edition, which is a model example for correspondence.

}\item {
A 20th century manuscript letter from \TeiEmphasisII{Robert Graves} where
emphasis has been put on visualizing rich encoding of semantic information in the
letter, in particular geographic and prosopographical data. 

}\end{itemize}

}\item {
For a taste of completely different encoding style we present several 19th century
lexicons and dictionaries:

\begin{itemize}
\item {
A manuscript collocative dictionary of Polish \TeiEmphasisI{Bogactwa
mowy polskiej} featuring interactive highlights for regions of interest
of the facsimile when hovering over dictionary headwords. Internal composition is
based on the \texttt{entryFree} element with a rich microstructure.

}\item {
A printed bibliography where TEI encoding aims to provide a basic researchable
structure to somewhat idiosyncratic attitude of the 19th century scholar.

}\end{itemize}

}\end{itemize}

\begin{mdframed}[frametitle={\paragraph*{Note}

}]
The list of samples is expected to grow and we'd like to encourage contributions
illustrating other genres and perspectives.

We'd like to stress that preparing showcases above has been only possible thanks to
numerous projects releasing their sources openly, in particular the \href{http://firstfolio.bodleian.ox.ac.uk}{Bodleian First Folio}, \href{http://www.deutschestextarchiv.de}{Deutsches
Textarchiv}, \href{http://vangoghletters.org}{Vincent
Van Gogh Museum} and \href{https://www.textcreationpartnership.org/tcp-eebo}{ EEBO-TCP}. We'd
also like to thank William Graves and Anna Skolimowska for sharing their correspondence
material. 

\end{mdframed}

\subsection*{Document View}

\label{document-view}
The document view can vary, depending on the sample document you are looking at.
Nevertheless some default functionality will be shared:

\begin{itemize}
\item {
the rightmost button in the toolbar opens the Settings
panel. Here you can change the ODD being used for display as well as the view template
(more about this later). By default, all sample documents apply the specific ODD which
fits them best, but you can play around and select another ODD to see what happens. 

\begin{figure}[h]
\caption{The Settings Panel}

\includegraphics[max size={\textwidth}{\textheight}]{odd-page-template-settings.png}

\end{figure}

}\item {
the leftmost toolbar button will open a \TeiEmphasisII{table of contents} (if
the viewed document has a division structure) 

}\item {
the Download menu allows you to download the currently
viewed document in a variety of output formats. Not all output formats work equally well
for all examples as we have not customized every example for every media. 

}\end{itemize}

\subsection*{Experimenting with ODDs and page templates}

\label{odd-experiments}
All TEI Publisher's sample documents are XML files which are transformed into a
HTML webpage for display in the browser. Two major factors determine how the final page is
going to look like: an \TeiEmphasisI{ODD} and a \TeiEmphasisI{page
template}. 

We have already mentioned in the very first section that the TEI Processing Model lies
at the heart of the Publisher - the ODD file associated with a document defines the rules of
transformation of the XML source file into HTML. Detailed discussion of the Processing Model
can be found in following chapters, for now it is
sufficient to say this is where decisions if a TEI element should be rendered inline, with a
tooltip, or as a marginal note, are made. Simplifying things a bit the
\TeiEmphasisII{text} of the document that you see rendered in your browser is an
effect of applying the rules from ODD file to the source document. 

Nevertheless, as we demonstrated in the section on selected sample documents, in the
application context we certainly want more than just text, however nicely typeset. From
basic navigation controls, table of content, to facsimile display, critical apparatus,
glossaries and maps - all of this and much more could be included in the final webpage.
Following \TeiEmphasisII{divide and conquer} approach the TEI Publisher defines such
specialized page elements as small, reusable blocks, using the Web Components technology.
Components can be used like common HTML elements, thus a page template is just an HTML
fragment which organizes the building blocks needed for a specific page. 

Looking more closely again at the TEI Publisher's Start page, we
can now give more detail what is happening when any of the sample documents is loaded. On
the right hand side there is a panel listing all ODD files available. Each of the sample
documents includes a processing instruction which specifies default ODD and page template
for this document. You can check what they are in Settings panel. For
the Graves letter it would be Graves' Letters ODD and
Letter with map/facets template. 

\begin{figure}[h]
\caption{The Settings Panel for the Graves Letter}

\includegraphics[max size={\textwidth}{\textheight}]{odd-page-template-settings.png}

\end{figure}

It is easy to experiment with different page templates and ODDs just changing these
options in the Settings panel. An important caveat though is that not
every page template makes sense for every document - after all parallel alignment can only
be successful if there is something to align, map needs coordinates to display, page view
needs information about page breaks and so on. 

\subsection*{Uploading your own documents}

\label{upload}
If you read this, in all likelihood you already have some documents of your own you
might want published, whether they are in TEI, DocBook, JATS, MS Word DOCX or other XML format.
The first step is to upload them into the database. You need to be \TeiEmphasisI{logged in} and in the Playground area to do it (check the short info on the
Start page for user name and password).

TEI Publisher installs two default application users:

\begin{description}
\item [tei-demo (default password: \TeiEmphasisII{demo})] 
This user can upload to the playground, annotations and jats collections. It can create new ODDs and
edit them. However, it cannot recompile ODDs other than the ones it created.

\item [tei (default password: \TeiEmphasisII{simple}] 
has full access to all collections, can change all ODDs, generate apps etc. On a public server we
strongly recommend to change at least this user's password.

\end{description}
Upon successful login, uploading is just a
question of dragging your documents onto the Upload area. They will
become available in the document list immediately after upload is completed. 

\begin{figure}[h]
\caption{The Upload Panel}

\includegraphics[max size={\textwidth}{\textheight}]{upload.png}

\end{figure}

Congratulations, now you can view your documents! Try to experiment and find the ODD
and page template that best fits your needs and use it as a starting point for your own
customization, if necessary. Once you are ready with these you can generate your own application for your documents only, which
packs just what is needed for publishing into a standalone application package. 

If you attempt to upload a Microsoft Word document, the upload will automatically
trigger upconversion of Word to TEI, using a custom ODD for the tranformation. Please note
that the focus of this conversion is to preserve textual content, structure and basic
semantics of the text, not provide authoritative mapping of complete set of MS Word features
to TEI. Refer to DOCX handling section for more information. 

\begin{mdframed}[frametitle={\paragraph*{Note}

}]
Please bear in mind that while TEI Publisher aims to be a universal tool, the specific
components may make certain assumptions about data they are getting and if your documents
do not follow the same conventions it may be required to adjust parameters passed to the
components from the page template or the component logic.

By means of example - a table of content component assumes that the document
structure is represented by means of nested div elements and
section titles are given in head element. If your project rather
chooses numbered divisions (div1, div2) etc
it may be advisable to adjust this to avoid customizing all navigation, table of contents
and so on, but it is one of very rare cases where TEI Publisher exposes any predilection
for a particular flavour of TEI. 

Similarly, the template for aligned transcription and translation is parametrized to
accept an XPath expression pointing to the location of the transcription and aligned
translation. Likely for your documents this expression would have to be adjusted (unless
of course you also have Latin texts with Polish translation structured in a similar way).
Furthermore, to correctly display corresponding translation fragment a custom mapping
function may need to be passed to the translation view (cf. \href{templates/pages/vangogh.html}{
Van Gogh
} or \href{templates/pages/cortez.html}{
Cortés
} letter templates for examples) 

\end{mdframed}

\section*{Supported XML vocabularies}\markboth{Supported XML vocabularies}{Supported XML vocabularies}

\label{supported-input-formats}
TEI Publisher started as a publishing toolbox for TEI but the principles of the TEI Processing
Model were never limited to a single vocabulary. Publisher very quickly extended support to
other XML formats. Currently TEI, DocBook, JATS and MS Word DOCX are supported out of the box
(DOCX via automated conversion to TEI on upload).

Few specificities of \TeiEmphasisII{TEI} and \TeiEmphasisII{DocBook} are listed
below, while \TeiEmphasisII{DOCX} is discussed at length in the following section. 

\subsection*{TEI}

\label{format-tei}
In principle, any TEI document will be supported by TEI Publisher and can be displayed
with the default page template and odd.

Nevertheless, certain assumptions are made about encoding of the basic structure of the
TEI documents for the purpose of navigation:

\begin{itemize}
\item {
page beginnings are encoded with <pb>

}\item {
column beginnings are encoded with <cb>

}\item {
structural divisions in the document are encoded with <div> elements

}\end{itemize}

We acknowledge that TEI offers other ways to encode these features, e.g. generic
<milestone> element or specialized numbered division elements like
<div1>, <div2>. TEI documents using alternative encodings will be still
displayed as specified in the ODD, it is only for the sake of navigation or division-based
full text search that we had to assume certain conventions to be able to decide what to show
as the next page, column or division. 

We believe our choice represents most common way of using TEI but, for those who
followed the path less travelled, the chapter on 
customization briefly discusses how to change relevant functionality. 

\subsection*{DocBook}

\label{format-docbook}
DocBook support is demonstrated by this very document you are now reading, 
documentation.xml. It is written in DocBook and presented via dedicated
docbook.odd and documentation.html page
template. 

You will notice a custom processing instruction in the source code of this document
which specifies which ODD and template to use. Experiment changing the template and ODD via
Settings drawer to see how much impact it has on display. 

\begin{lstlisting}[language=xml]

<?teipublisher odd="docbook.odd" template="documentation.html" depth="3"?>

\end{lstlisting} 

\subsection*{JATS (Journal Publishing Tag Library)}

\label{format-jats}
The JATS ODD currently supports \href{https://jats.nlm.nih.gov/publishing/tag-library/1.2/}{NISO
JATS Version 1.2}. It covers many elements commonly used for journal articles in the humanities, and can be 
easily customized for more specific use cases or encoding flavours.

By default, all documents in collection data/jats are associated with the JATS ODD (see
config:collection-config in modules/config.xqm.

\subsection*{MS Word DOCX format conversion}

\label{docx}
Starting with the version 5.0.0 of the TEI Publisher a new docx handling module is
available to allow for ingesting documents in \TeiEmphasisII{docx} format. Goal of this
module is to provide a way to import Word documents, preserving their textual content,
structure and basic semantics of the text, not to provide an authoritative mapping of
complete set of MS Word features to TEI. 

Docx format is relatively flat, thus reconstructing logical document structure like
divisions, lists and similar can be only based on certain heuristics. Likewise it is
impossible to deduce semantics attributed to certain formatting decisions. For that reason
TEI Publisher by intention ignores many style properties — trying to preserve as much as
possible would likely just add unnecessary "noise" and result in low-quality TEI. 

\subsubsection*{A word about Word}

\label{docx-intro}

A Word document is essentially a zip archive of several different XML files. These
files store various parts - the text content, styles, embedded media files etc.
Information most relevant for the import process have been extracted into a map, which is
passed as a parameter to the ODD, so it is available for every element. Thus information
about numbering styles can be accessed via \texttt{\$parameters?nstyle(.)} function and
testing if a list is bulleted could be done checking the value of \texttt{
\$parameters?nstyle(.)/numFmt/@w:val}. Full list of available functions and some
hints how to customize default conversion ODD are provided at the end of this chapter. 

\begin{figure}[h]
\caption{MS Word archive structure}

\includegraphics[max size={\textwidth}{\textheight}]{wordStructure.png}

\end{figure}

\begin{description}
\item [Named tei:* styles] 
Named styles can be strong indicators for the semantics of the text fragment.
Styles whose name starts with \texttt{tei:} are thus recognized as TEI elements
with the same name. If a character sequence uses a style called
\texttt{tei:persName}, it will be wrapped into a TEI <persName>
element in the output, e.g. \texttt{<persName>Johann Wolfgang
Goethe</persName>}. A place name should be marked with a style \texttt{
tei:placeName} and reconstructed text could be encoded by applying a style
\texttt{ tei:supplied}. 

\item [Headings and divisions] 
Since Word does not have a concept for text division, instead storing just flat
lists of paragraphs, so the only way to reconstruct the logical structure is to use
Word headings and outline level associated with these to determine division
boundaries. 

In the first pass, all paragraph styles starting with \texttt{heading},
\texttt{ title} or \texttt{subtitle} generate a <tei:head>
element. The outline level assigned to the heading is recorded as well. 

Subsequently, in a second pass through the generated output, divisions are
generated based on the outline level: a <div> spans all text from the
heading to the next heading on the same outline level and the process is repeated
for all headings within the division on a lower outline level. 

\item [Lists] 
Lists structure needs to be reconstructed, very much like divisions, taking
into consideration the list level associated with every item which can be accessed
via a call to \texttt{\$parameters?pstyle(.)//outlineLvl/@w:val}. 

\item [ Foot- and endnotes] 
Footnotes are translated into TEI note elements. Endnotes are also supported
and transformed into \texttt{<note type="endnote">}. 

\item [Tables] 
Processing of simple tables works very well as well as cells spanning multiple
colums. Row spans are not implemented yet. 

\item [Images] 
Embedded images are stored into a subcollection starting with the name of the
docx file being processed and suffixed with \texttt{.media}, eg.
\texttt{<graphic url="test.docx.media/image1.png"/>}

\end{description}

\subsubsection*{ODD for docx}

\label{docx-functions}
The ODD used for docx processing can be found in \href{odd/docx.odd}{docx.odd}. Users are free to extend the default ODD with additional
heuristics. For example, a paragraph being entirely bold could also be treated as a
heading, or a left text indent may indicate a quote. 

For testing purposes there is a Word document provided in 
data/doc/test.docx which includes samples of most important features like
headings, lists, tables, notes and embedded images. Try uploading it via upload panel as
described in the upload section and check the conversion
results. Behaviour of the conversion mostly follows the approach used in TEI Stylesheets
docx-to-tei transformation module and has been tested on test files included there. 

\paragraph*{Parameter functions}

\label{docx-functions-parameters}
Functions below can be used to retrieve styles or other information related to a
current node. For more usage examples see \href{odd/docx.odd}{
docx.odd}

\begin{description}
\item [cstyle] 
phrase level (characters, words or phrases) styles associated with the current
node

Returns: \texttt{w:style}

Usage example: \texttt{\$parameters?cstyle(.)/name[starts-with(@w:val,
'tei:')]}

\item [endnote] 
content of the endnote

Returns: \texttt{w:endnote/w:p}

\item [footnote] 
content of the footnote

Returns: \texttt{w:footnote/w:p}

\item [link] 
external link

Returns: \texttt{rel:Relationship}

Usage example: \texttt{\$parameters?link(.)/@Target}

\item [nstyle] 
list style information associated with the current node

Returns: \texttt{w:lvl}

Usage example: \texttt{\$parameters?nstyle(.)/numFmt}

\item [pstyle] 
paragraph level styles associated with the current node

Returns: \texttt{w:style}

Usage example: \texttt{\$parameters?pstyle(.)/name[matches(@w:val, 'quote';,
'i')]}

\end{description}

\section*{Processing Model transformations}\markboth{Processing Model transformations}{Processing Model transformations}

\label{odd-customization}
While TEI Publisher already provides various ODDs and page templates targeting specific
domains, it is likely that your project may require certain adjustments to fully meet your
needs. It has been one of primary concerns in Publisher's design that customization is not
only possible on various levels but also encouraged and we aim it to be as simple as
possible.

Very broadly we can group customization needs into two sets: changing the rules for
document transformation (how the source document is translated into the output format) or
changing the organization and styling of the rendered web page. In this chapter we'll
concentrate on the former, document transformation, which primarily requires modification of
the ODD with the TEI Processing Model. The latter would
require adjustments of the page template. In
both cases, it may be best to choose as your starting point an already existing ODD or page
template and adjust it. 

\subsection*{ODD Customization}

\label{odd-customization-details}

\subsubsection*{Creating Your First ODD}

\label{odd-customization-first-odd}
The general workflow for creating a customization is as follows: \begin{enumerate}
\item {
upload a TEI sample document you want to format

}\item {
create a new ODD

}\item {
modify the ODD to match your requirements

}\end{enumerate}

For the purpose of this quickstart, we will reuse one of the pre-installed sample
documents, but create a new ODD for it.

\begin{enumerate}
\item {
Log in and fill out the form at the bottom of the panel listing ODD files. Choose
a name for the ODD, e.g. myletter (without a suffix) and a title,
which will appear in the list after creation. Click on Create
button.

The newly created ODD should appear in the side panel.

}\item {
In the document list, click on \TeiEmphasisII{Letter \#6 from Robert Graves to William
Graves} to open it in the document viewer. 

}\item {
Open the Settings panel (rightmost toolbar button, see
above) and choose your ODD from the dropdown showing available ODDs. You may also
change the used HTML template to Default single text layout, though
this is not absolutely necessary. 

}\item {
The view should change and display the letter's content with only basic
formatting applied. Since our ODD has just been created and is empty, we see the
content with standard formatting applied. Our ODD by default inherits from 
teipublisher.odd. The latter is maintained by the e-editiones community
and contains processing model declarations for the most common TEI elements. Thanks
to this inheritance mechanism, many documents display nicely without requiring a lot
of additional customization. 

}\item {
From the menu, select Admin / Edit
ODD to open the visual ODD editor. 

}\end{enumerate}

\subsubsection*{Modify the ODD}

\label{modify-odd}
Changing processing models in the ODD is a powerful mechanism through which you can
control all aspects of the transformation of your documents from source XML format to all
output formats: HTML, ePUB, PDF etc. As already mentioned it is considered best practice
to chain ODD customizations together and rather change or add project specific rules to
more generic ODD than copy them in extenso. ODD chaining allows for the future upgrades as
your base ODDs may be updated by standardization bodies which maintain them. Commonly
project ODDs would extend teipublisher.odd, a generic TEI Publisher
set of processing rules. 

Beginning with version 3.0 of TEI Publisher, you have the choice between writing the
ODD by hand or using a visual editor. Both approaches can be combined and mixed. The
visual editor saves the ODD in a non-destructive way, preserving any information not
related to the processing model. It is thus safe to switch between hand-editing the ODD
and using the visual editor. Just make sure you reload the visual editor view after
modifying the source XML and vice versa. That said, visual editor is specifically tailored
to editing processing models so it will be likely the fastest and safest way to edit your
ODD.

To be able to customize the display of your document it is crucial to understand its
XML structure well. Each of processing models needs to be aimed at a particular XML
element and sometimes is only meant for a specific XML context - let's say we might want
to distinguish between headings of first and second level of nested divisions as they
often represent titles of different text units: acts and scenes or books and
chapters.

We'll start with the Graves' letter you have already viewed applying your custom ODD
in previous section. The display is quite simple and easy to read but we might want to
adjust it to follow common visual conventions for a letter, starting with displaying the
dateline on the right hand side and completely removing the page label which currently
sits there.

To create a processing model addressing this need we have to know 3 things: 

\begin{itemize}
\item {

\TeiEmphasisI{when} should it be applied, 

}\item {

\TeiEmphasisI{what} is supposed to happen 

}\item {
and \TeiEmphasisI{how} should the text be formatted? 

}\end{itemize}

To be able to answer the first question, you should familiarize yourself with the XML
structure of the letter to find out how datelines are represented in TEI. In the tab
displaying the letter, select Download / XML
to open \href{data/test/graves6.xml}{
graves6.xml
} in eXide. Quick investigation of the TEI encoding will reveal that dateline
resides in its eponymic tag <dateline> wchich is nested in the <opener>
part of the document, while page labels are encoded with <pb>. 

We'll use the visual editor, but show the corresponding ODD XML below each
screenshot. At the end of this chapter we'll describe how to edit the ODD XML code by hand. 

\subsubsection*{First Steps}

\label{visualodd}
The visual ODD editor opens if you select Admin /
Edit ODD from the menu while viewing a document.
Alternatively you can click on the name of an ODD in the list of ODDs on the TEI Publisher
entry page. A new tab opens, showing an action panel to the left, and the title of your
ODD to the right. 

\begin{mdframed}[frametitle={\paragraph*{Note}

}]

\TeiEmphasisII{Most recent versions of the ODD editor will look slightly different,
nevertheless they are functionally equivalent to the screenshots below, created in an
earlier version.}

\end{mdframed}
We need to overwrite the processing model rules for <dateline>. Enter
dateline into the input box next to the
New button in the left panel and click the button. This will
insert a processing model rule for < dateline> into the right panel. Because
<dateline> already exist in the base ODD,
teipublisher.odd, you'll see a single model which was copied from the
base ODD. 

\begin{figure}[h]
\caption{ Screen after adding <dateline>
}

\includegraphics[max size={\textwidth}{\textheight}]{editor-screen1.png}

\end{figure}

The corresponding ODD XML looks like this:

\begin{lstlisting}[language=xml]
<elementSpec mode="change" ident="dateline">
<model behaviour="block"/>
</elementSpec>
\end{lstlisting} 
Let's cover some key concepts of the TEI processing model first:
<elementSpec> primarily documents the structure, content, and purpose of an
element. It is a core element in any ODD but the schema-related functions are not relevant
for the discussion here. What is important for us is this is where processing models are
defined. The  @ident attribute of the <elementSpec>
identifies the name of the element to which the spec (and therefore processing model)
applies. 

An <elementSpec> may contain one or more <model> elements to
specify the intended processing of this element. Every model maps the element to a
behaviour. A behaviour denotes an abstract transformation function to
be applied. The TEI guidelines currently list two dozen behaviours, e.g. paragraph,
heading, note, inline, block. The last two are the most frequently used. How exactly a
behaviour translates into the target output media may differ depending on media features
and design decisions. TEI Publisher tries to implement them as generically as possible. 

To change the model expand it by clicking on the arrow to the left of the grey box. A
form appears, allowing you to change the model configuration. In our example we are happy
with \TeiEmphasisII{what} is happening with the dateline, so we don't need to change
the behaviour but we do want to fix \TeiEmphasisII{how} it is styled by justifying it
to the right. Rendition can be defined in an <outputRendition>, so click on the
+ button next to Renditions. In the form
input being inserted below, enter your styling requirements in css. 

The processing model uses <outputRendition> and CSS to define visual
aspects. For output formats other than XML, the CSS is translated into the corresponding
target language. It is thus best to limit the CSS to the most common typographical
features, like bold, italic, color, underline etc. The general styling of the text should
be done outside the ODD to maintain a clear separation of concerns. 

\begin{figure}[h]
\caption{ Add a rendition for <dateline>
}

\includegraphics[max size={\textwidth}{\textheight}]{editor-screen2.png}

\end{figure}

Again here's the corresponding XML:

\begin{lstlisting}[language=xml]
<elementSpec mode="change" ident="dateline">
<model behaviour="block">
<outputRendition>text-align: right;</outputRendition>
</model>
</elementSpec>
\end{lstlisting} 
To test your change, click on Save in the left panel and wait
a second until a popup appears. Switch back to the tab with Graves' letter from which you
opened the editor and refresh the browser window to see your changes applied. In case you
do not see any change, make sure 

\begin{enumerate}
\item {
you selected the correct ODD for viewing (check the
Settings drawer) 

}\item {
if you made changes to outputRenditions only, you may need to clear your
browser's cached version. For most browsers, holding the \TeiEmphasisII{Shift}
key while clicking on the \TeiEmphasisII{Reload} button does the job. 

}\end{enumerate}

\subsubsection*{Other behaviours}

\label{odd-customization-other-behaviours}
We would also like to hide the page breaks as we do not have facsimiles available.
Add a new element spec for <pb>. Again the newly added spec already includes a
model with behaviour break. Just change this behaviour to
omit or delete the existing model and insert a fresh one with behaviour
omit. 

\begin{figure}[h]
\caption{ Omit <pb>
}

\includegraphics[max size={\textwidth}{\textheight}]{editor-screen3.png}

\end{figure}

\begin{lstlisting}[language=xml]
<elementSpec mode="change" ident="pb">
<model behaviour="omit"/>
</elementSpec>
\end{lstlisting} 

\subsubsection*{Predicates and multiple models}

\label{odd-customization-predicates}
Next up, we may want to highlight the various places and people occurring within the
text. They are all marked up with the <name> tag, using different
@type attributes. Create a new element spec for <name> and
supply some color to the names. 

\begin{figure}[h]
\caption{ Color the <name> tags }

\includegraphics[max size={\textwidth}{\textheight}]{editor-screen4.png}

\end{figure}

And the XML for the entire <elementSpec> : 

\begin{lstlisting}[language=xml]
<elementSpec ident="name" mode="change">
<model behaviour="inline">
<outputRendition>
color: #FF9900;
</outputRendition>
</model>
</elementSpec>
\end{lstlisting} 
This rule affects places and people alike since both these categories are marked up
with <name> tag. If we'd like to treat people and places differently we'd need
separate models for them and a mechanism to distinguish between the two. The processing
model uses predicate to make such distinctions: a model rule will only be
used if the XPath expression in its predicate matches the current node being processed.
Let's add another model and give it a predicate: 

\begin{figure}[h]
\caption{Distinguish places and people}

\includegraphics[max size={\textwidth}{\textheight}]{editor-screen5.png}

\end{figure}

\begin{lstlisting}[language=xml]
<elementSpec ident="name" mode="change">
<model predicate="@type='place'" behaviour="inline">
<outputRendition >
color: #0077FF;
</outputRendition>
</model>
<model behaviour="inline">
<outputRendition>
color: #FF9900;
</outputRendition>
</model>
</elementSpec>
\end{lstlisting} 
\begin{mdframed}[frametitle={\paragraph*{Important}

}]
The order of models within the element spec is important. If you move the model with
the predicate to the bottom, all names will appear in the same color again. This happens
because the processor walks through the models until it finds the first one matching the
current node. If the model without predicate is first, it will always win over the one
with the predicate!

Also, if there's more than one matching model, only the first will be chosen.

\end{mdframed}

\subsubsection*{Parameters}

\label{odd-customization-parameters}
All behaviours accept one or more parameters which are defined in the TEI guidelines.
Every behaviour has an implicit parameter called content, and, as
the name suggests, it specifies which part of the source document should be processed: by
default it uses the nested content of the node. You may overwrite this default and assign
it another value. Some behaviours take other specialized parameters. For example, the
alternate behaviour accepts two parameters:
default and  alternate. An alternate
switches between two alternative states. On the web this could take the form of a popup,
in print it is usually implemented as a footnote. 

To put this to a test, let's look at the <date> elements appearing within
the letter. Most of them also specify a normalized date in their
@when attribute. Seeing this may be helpful for the reader, for
example, to know that the  19th mentioned in the postscript refers
to 1957-12-19. However, we may want to present the normalized date
in a more readable way. XPath has a function format-date for the
purpose and we could use it to show a representation of the date nicely formatted in the
user's language. 

Add a new element spec for <date>. You'll already see 4 predefined models.
The first two are for print only, but the third one does indeed use behaviour 
alternate, which is exactly what we want. Change the parameter value for
alternate to format the date: 

\begin{figure}[h]
\caption{ Format the normalized date in @when
}

\includegraphics[max size={\textwidth}{\textheight}]{editor-screen6.png}

\end{figure}

\begin{lstlisting}[language=xml]
<elementSpec ident="date" mode="change">
<model output="print" predicate="text()" behaviour="inline"/>
<model output="print" predicate="@when and not(text())" behaviour="inline">
<param name="content" value="@when"/>
</model>
<model output="web" predicate="@when" behaviour="alternate">
<param name="default" value="."/>
<param name="alternate" value="format-date(@when, '[FNn], [D1o] [MNn], [Y]')"/>
</model>
<model predicate="text()" behaviour="inline"/>
</elementSpec>
\end{lstlisting} 

\subsubsection*{Screencast}

\label{odd-customization-screencast}
The screencast below recapitulates some of the modifications we just applied. It uses
an older version of TEI Publisher, but the basic concepts and controls are still the
same:

\begin{figure}[h]
\caption{Screencast}

\begin{center}
Not available in PDF edition. Go to \url{https://www.youtube.com/embed/avRO-b2BwUI?rel=0} to view.
\end{center}

\end{figure}

\subsubsection*{Edit the ODD XML by hand}

\label{oddxml}
To switch to the XML source code of the currently edited ODD from within the visual
editor, click on the button with the angle brackets in the toolbar of the left side panel.
If you made changes in the form, you need to save first to update the ODD. The ODD XML
will be opened in a new tab, showing eXist's browser-based editor, \TeiEmphasisI{
eXide}. 

While using \TeiEmphasisI{eXide} is sufficient for small edits, we
really recommend using specialized XML editor like \TeiEmphasisI{oXygen}
for serious work on your TEI files. It will help you with many tasks, starting with the
syntax and documentation. You can edit ODDs stored in eXist using Oxygen's \TeiEmphasisII{
webdav} support or the \TeiEmphasisII{eXist data source} function. 

\begin{mdframed}[frametitle={\paragraph*{Important}

}]
If you edit the ODD XML by hand, there are some caveats you need to be aware of:
the visual editor will automatically check if there are existing <elementSpec>
s for a new element in any of the ODDs your ODD inherits from. When editing by hand, you
need to do this yourself. It's best to always have the base \href{odd/teipublisher.odd}{
teipublisher.odd
} open on the side. It is located in the same collection as your odd, i.e.
/db/apps/tei-publisher/odd. 

For example, to modify the element spec for <dateline>, check 
teipublisher.odd, where you'll find a definition already. Copy it over to
your ODD and start modifying it. 

Pay attention to the @mode attribute on <elementSpec>.
You must set this to change if you are overwriting an elementSpec
which already exists in the inherited ODDs. If not, set it to
add. 

\end{mdframed}
To test any changes, switch back to the tab in which you viewed your document (e.g.
Graves' letter) and select Admin / Recompile
ODD from the menu. 

\subsection*{Processing Model Syntax}

\label{pm-syntax}
TEI gives users a lot of freedom: there's always more than one way to encode your
material! To maintain interoperability and sustainability, you need a way to formally
describe the schema used as well as document editorial guidelines and transcription
processes. TEI ODD was designed for the purpose of expressing all this in the TEI language
itself. But how a document should be rendered was previously still considered to be the
responsibility of external publishing software and could not be described within the
ODD.

The advent of the TEI Processing Model changed this! The intended processing for all
elements can now be expressed within the TEI vocabulary as part of the ODD thus fulfilling
its promise of \TeiEmphasisI{One Document Does It All}. Markup elements
are mapped to a small set of abstract transformation functions, called \TeiEmphasisI{ behaviours}. Basic styling features can be set directly within the ODD using
CSS. The processing model is media-agnostic: behaviours and rendition styles are
transparently translated into different output media types like HTML, XSL-FO, LaTeX, or
ePUB. A single ODD can handle a multitude of output media types with just a few small
adjustments. 

\subsubsection*{
<model> element }

\label{pm-syntax-model}

<model> element is primarily used to document the intended processing for a given
element. One or more of these elements may appear directly within an
<elementSpec> element specification to define the processing anticipated for
that element. Where multiple <model> elements appear, they are understood to
document mutually exclusive processing scenarios, possibly for different outputs or
applicable in different contexts. 

A processing model defines on an abstract level how a given element may be
transformed to produce one or more outputs. The model is expressed in terms of \TeiEmphasisI{behaviours} and their parameters, using high-level formatting
concepts, such as block, inline, 
note or heading. A processing model is thus a
template description, used to generate the code needed by the publishing application to
process the source document into required output. 

The example below depicts a situation where a single model is defined for the
<app> element. As no @predicate or
@output are specified, this model applies for all contexts in
which <app> may appear and all possible outputs. Thus all <app> elements
will be transformed into inline chunks of text containing only contents of <app>
's <lem> child and omitting any possible <rdg> children. 

\begin{lstlisting}[language=xml]
<elementSpec mode="change" ident="app">
<model behaviour="inline">
<param name="content" value="lem"/>
</model>
</elementSpec>
\end{lstlisting} 

\paragraph*{
<model> children and attributes: }

\label{pm-syntax-model-children}

\begin{itemize}
\item {

@predicate : the condition under which this model applies,
given as an XPath Predicate Expression 

}\item {

@behaviour : names the function which this processing model
uses in order to produce output; possible values include: alternate, block,
figure, heading, inline, link, list, note, paragraph 

}\item {

@output : identifier of the intended output for which this
model applies; applies to all output if no @output is present on a
<model>

}\item {

@useSourceRendition : whether to obey any rendition
attribute which is present in the source document 

}\item {

@cssClass : one or more CSS class names which should be
added to the resulting output element where applicable 

}\item {

<param> : allows to pass parameters to @behaviour function; parameters
available depend on the behaviour in question; when parameters are not explicitly
passed, default values for those are assumed; all behaviour functions use current
element as default content 

}\item {

<outputRendition> : supplies information about the desired output
rendition in CSS; its attribute @scope provides a way of defining
‘pseudo-elements’ eg: first-line, first-letter, before, after 

}\end{itemize}

Model explicitly specifying content parameter: for <app> entries only
content of its <lem> child is to be displayed (as an inline chunk of text): 

\begin{lstlisting}[language=xml]
<elementSpec mode="change" ident="app">
<model behaviour="inline">
<param name="content" value="lem"/>
</model>
</elementSpec>
\end{lstlisting} 
Model specifying output rendition: contents of <ex> elements are to be
displayed in italic and wrapped in parentheses: 

\begin{lstlisting}[language=xml]
<elementSpec mode="change" ident="ex">
<model behaviour="inline">
<outputRendition>font-style: italic;</outputRendition>
<outputRendition scope="before">
content:"(";</outputRendition>
<outputRendition scope="after">content:")";</outputRendition>
</model>
</elementSpec>
\end{lstlisting} 
Sometimes different processing models are required for the same element in
different contexts. For example, we may wish to process the <quote> element as
an inline italic element when it appears inside a <p> element, but as an
indented block when it appears elsewhere. To achieve this, we need to change the
specification for the <quote> element to include two <model> elements
as follows: 

\begin{lstlisting}[language=xml]
<elementSpec mode="change" ident="quote">
<model predicate="ancestor::p" behaviour="inline">
<outputRendition>font-style: italic;</outputRendition>
</model>
<model behaviour="block">
<outputRendition>
left-margin: 2em;
</outputRendition>
</model>
</elementSpec>
\end{lstlisting} 
The first processing model will be used only for <quote> elements which
match the XPath expression given as value for the @predicate
attribute. Other element occurrences will use the second processing model. Set of
multiple <model> statements is regarded as an alternation and only the first
model with @predicate matching current context is applied.

\paragraph*{
<model> output styling }

\label{model-styling}
The intended rendering for a particular behaviour of a processing model may be
specified in one or all of the three following ways.

\begin{itemize}
\item {
the @cssClass attribute may be used to specify the name
of a CSS style in an associated CSS stylesheet (read more on specifying CSS styles in the ODD) which is to be
applied to each occurrence of a specified element found (in a given context, for a
specified output), 

}\item {
the attribute @useSourceRendition may be used to
indicate that the rendition specified in the source document should be applied,

}\item {
the styling to be applied may be specified explicitly as content of a child
< outputRendition> element. 

}\end{itemize}

When more than one of these options is used, they are understood to be combined in
accordance with the rules for multiple declaration of the styling language used. 

It is strongly recommended that use <outputRendition> should be limited to
strictly editorial decisions, such as '\TeiEmphasisII{conjectures are to be displayed in square
brackets}' and not as means to record all typesetting and layout specific design choices.
The latter are discussed in the Custom CSS styling
chapter. 

The processing model library translates the CSS styles into the target media
format. Restrictions apply due to differences between the output formats. Not all CSS
properties are supported for every format. Please refer to the section on Output media settings for further information. 

\subsubsection*{
<modelSequence> and <modelGrp>
}

\label{pm-syntax-modelSequence}
Summary of elements that can be used to document one or more processing models for a
given element: \begin{itemize}
\item {

<model> describes the processing intended for a specific context 

}\item {

<modelSequence> (sequence of processing models) a group of model elements
documenting intended processing models for this element, to be acted upon in
sequence 

}\item {

<modelGrp> (processing model group) a group of model elements documenting
intended processing models for this element 

}\end{itemize}

The <modelGrp> element may be used to group alternative <model>
elements intended for a single kind of output. The <modelSequence> element is
provided for the case where a sequence of models is to be processed, functioning as a
single unit. Common use case would be to use modelSequence to generate table of contents
along with the reading text as shown in the example below: 

\begin{lstlisting}[language=xml]
<elementSpec mode="change" ident="body">
<modelSequence>
<model behaviour="index">
<param name="type" value="'toc'"/>
</model>
<model behaviour="block"/>
</modelSequence>
</elementSpec>
\end{lstlisting} 

\subsubsection*{Behaviours}

\label{behaviours}
The \href{http://www.tei-c.org/release/doc/tei-p5-doc/en/html/ref-model.html}{TEI
guidelines} document a number of default behaviours. TEI Publisher allows users to
add their own behaviours, either within the ODD itself or by writing XQuery code. The following section lists the default
behaviours. 

\paragraph*{Available Behaviours}

\label{behaviours-available}
Behaviour functions accept a range of parameters, depending on the function in
question. Where these parameters are left unspecified in the <model>, default
values are used. All functions take at least one parameter:
content. It will be added by default unless specified and
contains the nested content of the currently processed node. You may change this by
explicitely setting a  content parameter inside the model. 

In the parameter lists below we skip the content parameter
as it is available for every behaviour. Optional parameters are marked as \TeiEmphasisII{
optional} in parenthesis, followed by the output mode they apply for, if
relevant. 

\begin{description}
\item [alternate] 
Display alternating elements for displaying the preferred version and an
alternative, both at once or by some method of toggling between the two. The
concrete implementation depends on the output format.

\begin{longtabu} {X[p]X[p]}

\TeiTdI{Parameter} | 
\TeiTdI{Description}

default | 
the content to display by default
\\

alternate | 
alternate content
\\

persistent | 
(optional, web) show a persistent popup on click instead of a tooltip on
hover if parameter evaluates to an effective boolean value of true
\end{longtabu}

\item [anchor] 
Create an anchor to which you can link, identified by the given id.

\begin{longtabu} {X[p]X[p]}

\TeiTdI{Parameter} | 
\TeiTdI{Description}

id | 
the id
\end{longtabu}

\item [block] 
Create a block structure, usually a div in HTML or fo:block in fo.

\item [body] 
Create the body of a document. In HTML this will result in a <body>
tag.

\item [break] 
Create a line, column, or page break according to type.

\begin{longtabu} {X[p]X[p]}

\TeiTdI{Parameter} | 
\TeiTdI{Description}

type | 
e.g. "page", "column", "line"
\\

label | 
e.g. "p. 13v"
\end{longtabu}

\item [cell] 
Create a table cell. If the @cols or @rows attribute is specified, the cell
may span several columns/rows.

\item [cit] 
Show a citation, with an indication of the source.

\begin{longtabu} {X[p]X[p]}

\TeiTdI{Parameter} | 
\TeiTdI{Description}

source | 
the citation source
\end{longtabu}

\item [document] 
Start a new output document.

\item [figure] 
Make a figure with provided title argument as caption

\begin{longtabu} {X[p]X[p]}

\TeiTdI{Parameter} | 
\TeiTdI{Description}

title | 
a caption
\end{longtabu}

\item [graphic] 
Display the graphic retrieved from the given url.

\begin{longtabu} {X[p]X[p]}

\TeiTdI{Parameter} | 
\TeiTdI{Description}

url | 
the url to load the graphic from
\\

width | 
the width of the graphic, e.g. "300px", "50\%" ...
\\

height | 
the height of the graphic, e.g. "300px", "50\%" ...
\\

scale | 
a scaling factor to apply. If specified, width and height will be output
as percentage based on the scaling factor, which should be a number between
0 and 1.
\\

title | 
a title for the graphics element. Usually not shown directly.
\end{longtabu}

\item [heading] 
Creates a heading.

\begin{longtabu} {X[p]X[p]}

\TeiTdI{Parameter} | 
\TeiTdI{Description}

level | 
the structural level of this heading. In HTML mode, this translates to
<h1>, <h2> etc.
\end{longtabu}

\item [inline] 
Outputs an inline element.

\item [link] 
Create a hyperlink.

\begin{longtabu} {X[p]X[p]}

\TeiTdI{Parameter} | 
\TeiTdI{Description}

uri | 
the link url
\\

target | 
identifier of the tab to open the link in (only web output)
\end{longtabu}

\item [list] 
Creates an ordered or unordered list, depending on the type attribute (e.g.
type="ordered"). If a label is present before each item,
a description list is output instead, using the label as definition term. 

\begin{longtabu} {X[p]X[p]}

\TeiTdI{Parameter} | 
\TeiTdI{Description}

type | 
The type of list: use "ordered" for an enumerated list, or "custom" to
specify item labels in combination with the n parameter on
each listItem. The default is "unordered" for a list of
bullet points. 
\end{longtabu}

\item [listItem] 
Outputs an item in a list.

\begin{longtabu} {X[p]X[p]}

\TeiTdI{Parameter} | 
\TeiTdI{Description}

n | 
a label to use for the item
\end{longtabu}

\item [metadata] 
Outputs a metadata section, e.g. a <head> in HTML.

\item [note] 
create a note, often out of line, depending on the value of
\texttt{place} ; could be "margin", "footnote", "endnote", "inline" 

\begin{longtabu} {X[p]X[p]}

\TeiTdI{Parameter} | 
\TeiTdI{Description}

place | 
defines the placement of the note, e.g. "margin", "footnote" ...
\\

label | 
the label to use for the footnote reference, usually a number.
\end{longtabu}

\item [omit] 
Do nothing, skip this element, do not process children 

\item [paragraph] 
Create a paragraph. 

\item [row] 
Create a table row. 

\item [section] 
Create a new section in the output document. In HTML mode, this translates to
a <section> element being output.

\item [table] 
Create a table.

\item [text] 
Output literal text.

\item [title] 
Output the document title. In HTML mode, this creates a <title> element.
In LaTeX, it adds the title to the document metadata.

\item [webcomponent (TEI Publisher extension)] 
Outputs a custom HTML element (usually referencing a webcomponent) using the
value of parameter name as tag name. All other parameters
are copied into corresponding attributes (properties of the webcomponent). 

\begin{longtabu} {X[p]X[p]}

\TeiTdI{Parameter} | 
\TeiTdI{Description}

name | 
the tag name to use for the custom element. Must be a string value.
\end{longtabu}

\end{description}

\subsection*{Including General CSS Styles}

\label{external-css}
TEI Publisher is based on webcomponents, therefore styling of one document will not
interfere with the styling of another document on the same page. All styles are strictly
encapsulated within the component and do not "pollute" the global browser space. This also
has a downside though: CSS rules defined outside the <pb-view> have no influence on
the text styling inside the component (with some exceptions, mainly for properties which are
inherited down the HTML tree, e.g. font-family). 

However, putting \TeiEmphasisII{all} styling information into
<outputRendition> tags within the ODD is also not a good idea - it adds a lot of
redundancy and mixes editorial responsibilities with web design concerns. 

The recommended solution would therefore be to use CSS classes for repeating styling
aspects. TEI Publisher supports linking to an external CSS stylesheet from the \texttt{
encodingDesc/tagsDecl/rendition} section of the ODD. Just specify a relative link in
the @source attribute: 

\begin{lstlisting}[language=xml]

<rendition source="docbook.css"/>

\end{lstlisting} 
The file should be stored in the same collection as the source ODD it is referenced
from. The linked file should be a standard CSS stylesheet.

Note that unfortunately, editing renditions is not yet supported by the visual ODD
editor, so you will have to fall back to add the corresponding elements to the ODD by
hand.

Alternatively, one may also use the same TEI element <rendition> with the
@selector attribute to embed CSS rules directly in the ODD. 

\begin{lstlisting}[language=xml]
<rendition selector="h3">
font-family: serif;
font-weight: 400;
</rendition>
\end{lstlisting} 
Choose one of the two approaches, but do not mix them. In both cases make sure to
recompile the ODD after changes as the CSS is merged into the generated code!

An addition introduced in Publisher 6.0 allows to pass the external CSS file in
\texttt{load-css} attribute of \texttt{pb-view}. Recompiling ODD in this case is
not necessary, otherwise it is functionally equivalent to using ODD \texttt{rendition}.

\subsection*{Output Media Settings}

\label{output-media}
The library supports various output media formats and translates styles into the
corresponding format. Currently the following output modes are supported and can be used in
the @output attribute: 

\begin{description}
\item [web] 
Produces HTML output

\item [fo] 
Generates a PDF via XSL:FO

\item [latex] 
Creates a PDF via LaTeX

\item [print] 
Extends web output with a focus on Print and Paged Media

\item [epub] 
A specialization of the web output mode targetted at epub documents

\end{description}
The quality of the generated output may vary a lot for the fo and latex modes, depending
on the type of input document. The following section provides more details on the
configuration of the FO output option:

\subsubsection*{FO Output}

\label{output-media-fo}
When generating XSL:FO output, the implementation tries to translate the CSS rules
specified for renditions into the corresponding XSL:FO formatting properties. Not all CSS
properties are recognized or can be mapped to FO properties. Unknown properties defined in
a rendition will be ignored.

The default rendering for headings, paragraphs and the like is defined by a separate
CSS file. The implementation merges those defaults with the custom renditions given in the
ODD.

The library searches for default CSS styles in a file named 
<odd-name>.fo.css inside the specified output collection (in which the
generated XQuery files are stored). The style definitions are copied literally into
attributes on the output XSL:FO elements, so any property which is a valid attribute for
the corresponding element may be used. For example,
teipublisher.fo.css contains: 

\begin{lstlisting}

.tei-text { font-family: "Junicode"; hyphenate: true; }
.tei-floatingText { padding: 6pt; }
.tei-p { text-align: justify; }

\end{lstlisting} 
Every XSL:FO document needs a master layout and a page sequence definition. Because
those tend to be rather verbose as they include things like page margins etc., they are
read from two XML files:

\begin{description}
\item [master.fo.xml] 
Contains the layout master set

\item [page-sequence.fo.xml] 
Defines the main page sequence

\end{description}
The mechanisms for configuring FO output are still very much under development and we
welcome suggestions by users.

\subsubsection*{LaTeX Output}

\label{output-media-latex}
The latex output mode produces good results for longer texts which fit well into the
pre-defined LaTeX environments. The number of supported CSS properties is limited
though:

\begin{itemize}
\item {
font-weight

}\item {
font-style

}\item {
font-variant

}\item {
font-size

}\item {
color

}\item {
text-decoration

}\item {
text-align

}\item {
text-indent

}\end{itemize}

To create arbitary complex LaTeX output, you may want to use the 
<pb-template> extension  to the ODD syntax. It is heavily used to e.g.
generate the LaTeX version of this documentation. See also \href{odd/serafin.odd}{serafin.odd} or \href{odd/vangogh.odd}{vangogh.odd} for examples. 

TEI Publisher creates a default LaTeX prolog based on standard packages and settings.
You may overwrite the defaults by providing your own template within the ODD element spec
for the TEI root element. See the example ODDs mentioned above. Note that TEI Publisher
will generate some LaTeX macros for styles defined in <outputRendition> which
should be imported into the prolog. The styles are added to the default configuration map
and can be accessed via \$config('latex-styles'). Refer to the example
ODDs and just copy/paste the corresponding lines. 

This output mode requires a local installation of LaTeX on the machine running TEI
Publisher. The examples have been tested on a default installation of MacTeX 2018. If you
are not running MacTeX, you likely need to adjust the path to the LaTeX binary in the
XQuery configuration module modules/config.xqm. Search for the
variable \$config:tex-command and adjust it to point to a binary of
xelatex, pdflatex or lualatex
. 

\subsubsection*{ePub Output}

\label{output-media-epub}
The epub output mode extends the HTML mode. You may define
general styling in an extra CSS file, located in
resources/css/epub.css. This external stylesheet is included into
all generated epub files and may be used to configure general settings like page breaks,
hyphenation, font sizes etc. 

\subsubsection*{Print CSS}

\label{output-print-css}
This output mode targets printed HTML via the CSS Paged Media specification (often also called Print CSS).
Though recently improved, browser support is still incomplete. However, there are numerous tools to fill the gap. 
Select the print CSS download option for any of the documents in TEI Publisher which
support it and you will be directed to a preview page. This page uses a library called \href{https://pagedjs.org/}{paged.js} to "\TeiEmphasisII{teach}" the browser how to handle
certain layout aspects. Thanks to this, using the print page dialog of
your browser will result in a much nicer page layout than if you just tried to print TEI
Publisher's document view.

You can find a more detailed discussion of the feature along with some CSS examples in this \href{https://www.e-editiones.org/posts/print-css/}{article on the
e-editiones homepage}.

The preview page uses TEI Publisher's \texttt{pb-print-preview} web component.
This component will retrieve the full HTML of the document, enhanced with additional CSS
stylesheets for print, and passes it to paged.js for the page formatting. For testing
purposes you can also click on the bottom-most button with the eye
icon to see the raw HTML (without paged.js applied). This is handy if you want to inspect the HTML node
hierarchy or the CSS classes assigned.

To generate the HTML of the document, the component calls Publisher's API
endpoint:

\begin{lstlisting}
/api/document/doc%2Fdocumentation.xml/print
\end{lstlisting} 
The following (optional) parameters are supported:

\begin{description}
\item [base] 
specifies the base URI for resolving relative links, e.g. to locate
images

\item [style] 
one or more additional CSS stylesheet URLs to be imported into the page.

\item [script] 
one or more Javascript files to be loaded via <script>.

\item [wc] 
if set, include TEI Publisher's web component libraries. You may need this if
you are using components like <pb-code-highlight> (as in the
documentation)

\end{description}

As an open source project, paged.js does not support every fancy layout
you may wish for. For example, support for formatting footnotes will be limited. There are
other, mainly commercial tools, which you may use to generate PDF out of your HTML. Those
include e.g. \href{https://www.princexml.com/}{Prince XML}, \href{https://www.pdfreactor.com/}{PDF Reactor} or \href{https://antennahouse.com/}{Antennahouse}. A full list can be found on \href{https://www.print-css.rocks/tools}{print-css.rocks}. Each of those may have
different strengths and weaknesses. Please try yourself.

For command line tools, you can use the API endpoint described above to retrieve the
full HTML of the page and feed this to PrinceXML or whatever you want to use. To simplify
this, the preview page includes a button at the bottom: clicking it will copy the API
endpoint URL (excluding the page.js components, which would interfere with external
tools). The screenshot below shows princeXML's dialog into which you can paste the URL
provided by the preview page:

\begin{figure}[h]
\caption{ Processing Print HTML with PrinceXML }

\includegraphics[max size={\textwidth}{\textheight}]{prince-screenshot.png}

\end{figure}

\subsection*{Extensions to the Processing Model Specification}

\label{pm-extensions}

\subsubsection*{XQuery Instead of XPath}

\label{pm-extensions-xquery}
The implementation directly translates processing model instructions into an XQuery
3.1 module by generating executable XQuery code. This is straightforward as the resulting
XQuery will closely resemble the specification in the ODD, thus being easy to debug. It
also leads to very efficient code, which is as fast or even faster as a hand-written,
optimized transformation.

As a welcome side effect, any valid XQuery expression might be used wherever the spec
expects an XPath expression, e.g. in predicates or parameters. For example, one can define
variables inside a parameter using a standard XQuery \texttt{let \$x := ...
return ...} syntax. 

\subsubsection*{Default Processing Model Rules}

\label{pm-extensions-default}
It is possible to define a default <elementSpec> to be applied to all
elements which are not already matched by another elementSpec. For example, if no <
elementSpec> is present for an element, its text content is output. To change this
behaviour and omit content elements without specification, you may want to define a
default <elementSpec> as shown below: 

\begin{lstlisting}[language=xml]
<elementSpec ident="*"> <model behaviour="omit"/> </elementSpec>
\end{lstlisting} 
You can also define models to be applied to all text nodes, e.g. if you need to
normalize certain nodes:

\begin{lstlisting}[language=xml]
<elementSpec ident="text()">
<model behaviour="text"/>
</elementSpec>
\end{lstlisting} 
Note that outputting text nodes is a performance critical operation, so use with care.
Too complex processing may dramatically slow down rendering.

\subsubsection*{Setting processing parameters for the ODD}

\label{setting-parameters}

Depending on the application context we often wish to differentiate the desired
processing output. For example when displaying the list of documents available in an
edition we usually only want to see a rather short entry comprising of the author and
title, but when viewing an individual document we certainly want to present all associated
metadata, not to mention arrange that information visually in a distinct way. 

To this end, we can pass external parameters into the ODD, which inform the processor
which of the processing scenarios we wish to follow.

In a External parameters section you can read more about this, 
the most common, use case for passing parameters in the ODD.

In version 3.0.0 of the \texttt{tei-publisher-lib} we added two carefully chosen
features to our implementation of the TEI Processing Model: 

\begin{itemize}
\item {
a method to specify a processing mode passed to all subsequently called
models

}\item {
a way to set a parameter, so it will be available to subsequently processed
models

}\end{itemize}

The first is implemented as a specialization of the second. Both features are
intended for relatively rare cases, where the standard mechanisms for handling the flow of
processing are not enough. This mainly applies to cases in which you have to process the
same part of the TEI document multiple times in the same processing context (usually
\texttt{pb-view}). None of the examples shipping with TEI Publisher needs these
features, but in elaborate editions we do encounter situations which cannot be handled
without them. 

\paragraph*{External Parameters}

\label{external-parameters}
The script calling the processing model may pass external parameters into the ODD.
They will be available in the variable \$parameters, which is an
XQuery map. Access parameters using \texttt{?}, the XQuery lookup operator. 

For example, one can use this feature to control how specific parts of the document
are output, without having to define a separate output mode, which would result in much
more code. Below we display a shortened header for the document, containing simply its
title, but only if the parameter "header" is set to "short":

\begin{lstlisting}[language=xml]
<elementSpec mode="change" ident="fileDesc">
<model predicate="$parameters?header='short' behaviour="block" cssClass="header-short">
<param name="content" value="titleStmt"/>
</model>
...
</elementSpec>
\end{lstlisting} 
The <pb-view> webcomponent also lets you define arbitrary parameters to be
passed to the ODD via <pb-param>. For example, the breadcrumbs shown above this
documentation page are realized by setting a parameter mode and
can be queried in model predicates with
\$parameters?mode='breadcrumbs' . 

\begin{lstlisting}[language=xml]
<section class="breadcrumbs">
<pb-view id="title-view1" src="document1" subscribe="transcription">
<pb-param name="mode" value="breadcrumbs"/>
</pb-view>
</section>
\end{lstlisting} 
If the parameter is set, the processing model rules in the ODD will output the
headings of all ancestor sections of the current division only, ignoring everything
else. This approach helps to reuse the same ODD for viewing specific aspects of the
document.

A dedicated user interface webcomponent \href{https://cdn.tei-publisher.com/api.html#pb-toggle-feature.0}{
<pb-toggle-feature>
} exists for toggling between two values of a parameter. Example below would
produce a checkbox which when on results in the value of 
\$parameters?mode set to diplomatic, otherwise to
norm. 

\begin{lstlisting}[language=xml]
<pb-toggle-feature name="mode" on="diplomatic" off="norm">Diplomatic View</pb-toggle-feature>
\end{lstlisting} 

\paragraph*{Processing Modes }

\label{pm-mode}
Distinguishing between processing modes is a common feature in XSLT. It comes handy
if you need to process the same XML more than once for different purposes. One common
example would be to render a person reference once in the running text and again, as a
footnote, but then perhaps together with the associated commentary but without
information about textual features related to the process of writing, like scribal
errrors in the spelling or gaps and stains on the parchment. As a rule of thumb, setting
a mode is helpful where it would not be possible to distinguish the scenario to apply
neither by the context in which the element appears in the XML source nor by the
external parameter passed into the ODD. 

tei-publisher-lib 3 allows you to specify this new extension attribute,
\texttt{@pb:mode}, on a \texttt{model}. The value of the attribute will be
taken as the name of the mode, and subsequently called models can check it (e.g. in a
\texttt{model}
\TeiEmphasisII{predicate}) via this special variable, e.g.
\texttt{\$mode="register"} if your model definition specified this value, e.g.
\texttt{<model behaviour="block" pb:mode="register">}. 

\paragraph*{Setting Parameters within the ODD}

\label{pm-set-param}
A logical follow-up for setting the processing mode described in the previous
section and passing external parameters, this
extension allows to set an arbitrary parameter which is passed on to all models
subsequently called as a result of processing the current element. 

The syntax is almost the same as for the standard \texttt{<param name="foo"
value="baz"/>}. Just the name of the element changes to
\texttt{<pb:set-param>}, marking this as a special parameter which is
"inherited" by subsequent models. 

Common motivation to use this feature would be for efficiency, to compute certain
value once and just use it many times afterwards. Let's imagine that every paragraph
exposes a citation button which always starts with the author, title and other
information from the publication statement part of the TEI file and only ends with a
paragraph number. We could easily prepare the initial sequence on a division level and
have it available to all nested paragraphs, thus saving the processing time required to
look up from the paragraph to the TEI header every time. 

\subsubsection*{Code Templates and Custom Behaviours}

\label{pm-extensions-templates}
The two dozen behaviours defined by the TEI processing model are enough to cover most
standard HTML output tasks like a listItem or heading, but more complex HTML markup or
even other output formats like LaTeX require more customization and control over the
generated output. The TEI Publisher library thus extends the processing model syntax with
two custom elements for defining code templates.

While TEI Publisher does provide ways to write your own behaviours in XQuery and thus
extend the ones defined in the guidelines, this should only be used as last resort: custom
XQuery behaviours limit the portability of the ODD and are bad for maintenance.

Avoiding custom behaviours works quite well for HTML output and we have realized
complex projects with just two or three extension behaviours. Things start to become more
difficult if you try to output LaTeX though: there are hundreds of packages to use, and
users typically define their own macros or environments for all recurring typesetting
tasks. For example, to print a TEI <persName>, experienced LaTeX users would
normally create a corresponding \texttt{\textbackslash persName} macro and handle the formatting
details there. Unfortunately, out of the box the TEI processing model does not facilitate
this level of customization. 

\paragraph*{ Introducing <pb:template>
}

\label{pb-template}
TEI Publisher supports an extension to the ODD syntax in its own namespace (
http://teipublisher.com/1.0). 

Within the ODD, a <model> may define a <pb:template> element
containing a code template. The template is expanded first and the result is passed into
the behaviour specified for the model, replacing the default
content parameter accepted by all behaviours. The very simple
case of outputting a <persName> in LaTeX could thus be written as: 

\begin{lstlisting}[language=xml]
<elementSpec ident="persName" mode="add">
<model behaviour="inline" output="latex">
<pb:template>\persName{[[content]]}</pb:template>
</model>
</elementSpec>
\end{lstlisting} 
The template can reference other parameters defined within the <model> by
enclosing the parameter name in double brackets. In the example above we're referencing
the default parameter content, which contains the nested content
of the <persName> tag. The parameter will be processed before it is passed into
the template, so if <persName> contains nested TEI markup, the corresponding
processing model rules will be applied first. 

The result of expanding the template then becomes the new
content parameter to be passed to the behaviour (
\texttt{inline} in the example above), which is processed in the normal way as
defined in the TEI guidelines. 

You may also specify additional parameters to be included in the template. For
example, the TEI document may contain a glossary of terms which are referenced in the
text using \texttt{<term ref="\#termid">text</term>}. In LaTeX this would
translate to \texttt{\textbackslash glslink\{ref\}\{text\}}, which can be easily produced by the
following <model> : 

\begin{lstlisting}[language=xml]
<elementSpec ident="term" mode="add">
<model behaviour="inline" output="latex">
<param name="ref" value="substring-after(@ref, '#')"/>
<pb:template>\glslink{[[ref]]}{[[content]]}</pb:template>
</model>
</elementSpec>
\end{lstlisting} 
We define an additional parameter ref, which contains the id
string from the @ref attribute, stripping out the leading '\#'. 

The templating mechanism is not limited to LaTeX, but may also be used to generate
HTML or FO, for example, if you have to generate a complex HTML fragment to represent a
single TEI element. This is hard and sometimes impossible to achieve without
templates

This following sample uses the pb-popover webcomponent to
display the tei:persName from a person register for a given tei:persName/@key of your
TEI document. 

\begin{lstlisting}[language=xml]
<elementSpec ident="persName" mode="add">
<model behaviour="inline" cssClass="popover">
<param name="content" value="."/>
<param name="key" value="@key"/>
<param name="person-from-register" value="doc('/path/to/person.xml')//person[@id = @key]/persName[@type='full']/text()">
<pb:template xmlns="" xml:space="preserve">
<pb-popover data-ref="[[key]]">
<span slot="default">[[content]]</span>
<span slot="alternate">[[person-from-register]]</span>
</pb-popover>
</pb:template>
</model>

\end{lstlisting} 

\paragraph*{Defining New Behaviours in the ODD}

\label{pb-behaviour}
By combining code templates with parameters we can come up with a very simple
mechanism to define new behaviours right inside the ODD!

Take the TEI Publisher documentation as an example: it is written in Docbook 5 and
transformed via ODD. The documentation includes some videos which are hosted on youtube.
In DocBook these are represented by <videodata> elements inside a <videoobject>.

\begin{lstlisting}
<figure xml:id="edit-odd">
<title>Screencast</title>
<mediaobject>
<videoobject>
<videodata fileref="https://www.youtube.com/embed/avRO-b2BwUI?rel=0" width="853" depth="480"/>
</videoobject>
</mediaobject>
</figure>
\end{lstlisting} 
In the HTML output we would need to transform this into an <iframe>, so
the reader can view the video embedded in the page. We can achieve this with a <
pb:template> as sketched in the previous section, but it would be nice to turn
this into a general-purpose behaviour, which we can re-use in other situations requiring
an iframe. The TEI Publisher library allows us to define a behaviour right inside the
ODD as follows: 

\begin{lstlisting}
<pb:behaviour ident="iframe" output="web">
<pb:param name="src"/>
<pb:param name="width"/>
<pb:param name="height"/>
<pb:template xmlns="">
<iframe src="[[src]]" width="[[width]]" height="[[height]]" frameborder="0" gesture="media" allow="encrypted-media" allowfullscreen="allowfullscreen"></iframe>
</pb:template>
</pb:behaviour>
\end{lstlisting} 

\begin{mdframed}[frametitle={\paragraph*{Note}

}]
Note how we have to reset the namespace on the <pb:template> ? This is
required because the default namespace in an ODD document is the TEI namespace. You
therefore need to reset it whenever you want to output elements in another or no namespace
inside a template. Without this, the iframe would end up in the TEI namespace.
Web browsers will usually ignore it, but it would be incorrect nevertheless. 

\end{mdframed}
All behaviours should be included in the TEI header or - to be exact: the <
tagsDecl> inside the <encodingDesc>. You may have multiple behaviour
declarations with the same @ident, given that they apply to
different @output modes. Parameters specified via
<pb:param> without @value attribute are expected to be
passed to the behaviour from the calling model. A parameter may be empty though. If you
define an XPath expression as @value attribute, the result of the
XPath evaluation will be used as value for the parameter. 

The new behaviour will be named iframe and takes three
parameters: src, width and 
height. It can now be called from a <model> as follows: 

\begin{lstlisting}
<model behaviour="iframe">
<param name="width" value="@width"/>
<param name="height" value="@depth"/>
<param name="src" value="@fileref"/>
</model>
\end{lstlisting} 
For further code examples, please have a look at \href{odd/docbook.odd}{docbook.odd}, which is used for viewing the documentation. 

\begin{mdframed}[frametitle={\paragraph*{Note}

}]
At the time of writing, the graphical ODD editor in TEI Publisher does not yet
support defining your own behaviours via <pb-behaviour>. You have to
make these changes in the source XML using eXide, oXygen or another XML editor. You
can, however, use the graphical editor to continue editing the ODD afterwards. It is
smart enough to not overwrite your hand-written code upon save. 

\end{mdframed}

\subsubsection*{Extension Modules}

\label{extension-modules}
Where possible, developers should stick to the standard behaviours defined by the TEI
guidelines, or use the <pb-behaviour> and <pb-template>
extensions of the ODD syntax. However, there might be
situations in which it is necessary to generate a specific type of complex output, which
requires the full power of XQuery. To facilitate this, the implementation allows
additional extension modules to be configured: 

\paragraph*{Configuration}

\label{extension-configuration}
Configuration is done via an XML file which must reside in the same collection as
the source ODD files. It contains a series of <output> elements, representing
particular output modes (e.g. web or print) via @mode attribute.
< output> element without a mode groups modules available for all output
modes. 

Each <output> element lists modules to be loaded for specified output
mode. Each definition may optionally be limited to a specific ODD, name of which is
specified in the @odd attribute. 

\begin{lstlisting}[language=xml]
<modules>
<!-- functions or behaviours common to all output modes -->
<output>
<module uri="http://www.tei-c.org/tei-simple/xquery/common-functions" prefix="tc" at="xmldb:exist:///db/apps/my-app/modules/common.xql"/>
</output>
<!-- General fo extension functions -->
<output mode="print">
<module uri="http://www.tei-c.org/tei-simple/xquery/ext-fo" prefix="ext-fo" at="xmldb:exist:///db/apps/tei-publisher/modules/ext-fo.xql"/>
</output>
<!-- Special web configuration for the documentation (to handle <code>) -->
<output mode="web" odd="documentation">
<module uri="http://www.tei-c.org/tei-simple/xquery/ext-html" prefix="ext-html" at="xmldb:exist:///db/apps/tei-publisher/modules/ext-html.xql"/>
</output>
</modules>
\end{lstlisting} 
Whenever the library tries to locate a processing model function for a given
behaviour, it will \TeiEmphasisI{first} check any extension module it
knows to see if it contains a matching function. One can thus \TeiEmphasisI{
overwrite} the default functions as well as define new ones. 

An extension module may also contain general purpose XQuery functions you want to
call from within an ODD parameter, e.g. for formatting a date, outputting a number etc.
To make those functions available to all output modes, just skip the
@mode attribute. 

\begin{mdframed}[frametitle={\paragraph*{Note}

}]
Starting with tei-publisher-lib 3.1.0, the module import path given in the "at" attribute
no longer needs to be absolute. A relative path (e.g. ext-html.xql) will be interpreted relative
to the modules collection.

\end{mdframed}

\paragraph*{Implementing Custom Behaviours}

\label{extension-modules-behaviours}
To be recognized by the library, an extension function must accept at least 4
default arguments, plus any number of custom parameters. The required parameters
are:

\begin{description}
\item [\$config] 
a map containing configuration information as well as function references to
be called. The most important ones are \$config?apply(\$config,
\$node) and \$config?apply-children(\$config, \$node,
\$content). Both are function items and when called, continue
processing with either a single  \$node or a sequence of
nodes in \$content. 

\item [\$node] 
the TEI element being processed at the moment

\item [\$class] 
a list of HTML class names to be used. This includes automatically generated
class names as well as those passed via @cssClass on a
model item. 

\item [\$content] 
because content is defined for every model rule, it is
always passed to a behaviour function (though it might be empty) 

\end{description}
For all additional parameters, the processing model implementation tries to fill
each custom parameter with a corresponding value by looking through the <param>
children of the <model> in the ODD to find one with a name matching the
variable name. If no matching parameter can be found, the function argument will be set
to the empty sequence. You should not enforce a type or cardinality for any of the
custom parameters as this may lead to unexpected errors. The parameters may be empty or
contain more than one item. 

For example, a custom behaviour called \texttt{code} for syntax highlighting in
an extension module named ext-html.xql might look as follows: 

\begin{lstlisting}
xquery version "3.1";
(:~ : Non-standard extension functions, mainly used for the documentation. :)
module namespace pmf="http://www.tei-c.org/tei-simple/xquery/ext-html";
declare namespace tei="http://www.tei-c.org/ns/1.0";

declare function pmf:code($config as map(*), $node as element(), $class as xs:string+, $content as node()*, $lang as item()?) {
<pre class="code {$class}" data-language="{if ($lang) then $lang else 'xquery'}">
{replace(string-join($content/node()), "^\s+?(.*)\s+$", "$1")}
</pre>
};
\end{lstlisting} 
It defines one function, pmf:code, which can be called from
the ODD as follows, provided that the ext-html.xql module has been
configured as described in the previous
section. 

\begin{lstlisting}[language=xml]

<model behaviour="code"> 
<param name="lang" value="@lang"/> 
</model>

\end{lstlisting} 

\paragraph*{Custom Behaviours Accepting User-Defined Parameters}

\label{extension-modules-behaviour-parameters}
Sometimes you may like to implement a generic behaviour which takes arbitrary
parameters from the user. This means the parameter list of your behaviour will not be
fixed.

To facilitate this, a behaviour function may declare a final parameter
\texttt{\$optional as map(*)}. If the processor finds <param> children in
the model which cannot be mapped to an explicitly declared parameter, it stores all such
extra parameters as a key/value pairs in the \$optional map.

\subsubsection*{Accessing Global Configuration Variables/Functions}

Sometimes you may want to access global configuration parameters, e.g. to determine
the data root collection of the current application. tei-publisher-lib
4.0.0 imported the entire modules/config.xqm into the
XQuery code generated from the ODD, and exposed it in the global
namespace. This way one could access the data root as
\$global:data-root inside a predicate or parameter expression in
the ODD. However, the complexity of config.xqm caused unnecessary overhead and failures on Windows.

Version 4.0.1 instead allows you to explicitely import one or more modules in the ODD
processing configuration file (odd/configuration.xml or
resources/odd/configuration.xml). 

\begin{lstlisting}[language=xml]
<modules>
<!-- Import global variables and functions from modules/odd-global.xqm -->
<module uri="http://e-editiones.org/tei-publisher/odd-global" prefix="global" at="odd-global.xqm"/>
...
</modules>
\end{lstlisting} 

\section*{Custom CSS styling}\markboth{Custom CSS styling}{Custom CSS styling}

\label{css-styling}

CSS stylesheet \texttt{resources/css/theme.css} defines styles used by all pages of
the TEI Publisher and Publisher-generated applications. Nevertheless, users \TeiEmphasisI{should not} directly modify this file but create a project-specific
css customization file and include it alongside \texttt{theme.css} instead. 

\begin{lstlisting}[language=html]

<link rel="stylesheet" href="resources/css/theme.css" />
<link rel="stylesheet" href="resources/css/my-project.css" />

\end{lstlisting} 
This approach allows to selectively overwrite certain styles and CSS variables from
\texttt{ theme.css} while remaining on the easy upgrade path for future TEI Publisher
and \texttt{ pb-components} updates. 

\subsection*{Customizing web components styling}

\label{css-styling-components}
A web component completely shields its content, so it cannot be styled from outside. Web
component styles remain encapsulated, preventing style contamination between individual
components and general application context. A blessing in general, allowing components to be
scripted and styled without the fear of collision with other parts of the page, but poses
additional challenges when adjusting the look and feel of a component to fit a project's
theme.

For Publisher, encapsulation of web components means that definitions in
\texttt{theme.css} or equivalent project customization CSS files are not able to
directly govern web components styling. 

Note that while you cannot directly change the inner appearance of a component, 
you can style the component itself within the
HTML template, e.g. to position it within the layout of the page.

With TEI Publisher 8, or, more precisely, version 1.43.0 of the
\texttt{tei-publisher-components}, a very robust method of applying styles throughout the page
is available by simply specifying a \texttt{theme} property for \texttt{pb-page}.

\begin{lstlisting}[language=xml]
<pb-page data-template="pages:pb-page" ... theme="resources/css/components.css">
\end{lstlisting} 

In older versions, some aspects of component styling remained unaccessible for customization. 
From Publisher version 6 \texttt{pb-components} certain style
properties are exposed to the outside world via standard CSS variables. This way variables like 
\texttt{--pb-footnote-color} defined in \texttt{theme.css} can be accessed by e.g.
\texttt{pb-view} component and thus determine the color of the footnote marker in the
rendered transcription. 

\subsection*{External stylesheets}

\label{css-styling-external}
ODD specification allows for explicit declaration of an external CSS file which may
define styles and CSS classes to be applied to tranformed sources (in \texttt{
encodingDesc/tagsDecl/rendition}), e.g. 

\begin{lstlisting}[language=xml]

<rendition source="docbook.css"/>

\end{lstlisting} 
Styles and classes from that file are loaded into \texttt{pb-view} component and
thus accessible for its content. 

External stylesheets for \texttt{pb-view} can also be specified via
\texttt{load-css} component configuration attribute. In this scenario, unlike with ODD
\texttt{rendition}, regenerating the ODD is not required for changes to the CSS file
to be applied, otherwise both methods are functionally equivalent. 

\begin{lstlisting}[language=html]

<pb-view id="view1" src="document1" load-css="odd/docbook.css"/>

\end{lstlisting} 

Broader discussion of using <rendition> for custom styles can be found in
this section. 

\section*{Page templates and pb-components}\markboth{Page templates and pb-components}{Page templates and pb-components}

\label{webcomponents}
As described earlier, the various sample documents included in the TEI Publisher Demo
collection differ not only in the ODD they use, but also concerning the general layout and
composition of the page. They are based on different HTML templates, which can be found in the
templates/pages collection of the TEI Publisher app. Each template
assembles various building blocks in a slightly different way - some  examples show a facsimile view next to the text, others
a parallel display of transcription andtranslation, some include a map and another showcase
collapsible metadata section. Which template is being used is determined by a processing instruction in the TEI sources of these examples. 

The building blocks we mentioned are custom HTML elements. Each of them encapsulates a
certain functionality and appearance. The map, the facsimile, but also the text view itself
and all controls are custom HTML elements. They are like "Lego" blocks which can be freely
moved around and rearranged without knowing anything about internal implementation of the
component.

\subsection*{Web Components}

\label{webcomponents-intro}

The technology enabling this Lego-like modular approach is a W3C standard called
\TeiEmphasisII{Web Components}. It is already built into many browsers and support is
improving quickly, reducing the need for external frameworks. There's a growing collection
of ready-to-use components available, e.g. the \href{https://www.webcomponents.org/author/PolymerElements}{Polymer elements}
we use for menus, buttons, dropdowns etc. TEI Publisher from version 6.0 exposes its
collection of Web Components targeted at creating digital editions as a separate \texttt{
pb-components} package. 

You do not need to know much about \TeiEmphasisII{Web Components} to use them in
TEI Publisher. From a user perspective, a component looks like any other HTML element. You
configure it by setting its properties via attributes. For example, the following HTML code
snippet will display the first page/section of two completely different documents as you can
see below in the embedded \href{https://codepen.io/}{Codepen} (to learn more on embedding Publisher output and components see further chapters) 

\begin{lstlisting}[language=xml]

<pb-page>
<pb-document id="document1" path="test/kant_rvernunft_1781.TEI-P5.xml" odd="dta" view="page"></pb-document>
<pb-document id="document2" path="doc/documentation.xml" odd="docbook" view="div"></pb-document>

<!-- Display two document views side by side -->
<main>
<pb-view id="view1" src="document1"></pb-view>
<pb-view id="view2" src="document2"></pb-view>
</main>
</pb-page>
\end{lstlisting} 

\begin{lstlisting}

\end{lstlisting} 

<pb-page>, <pb-document> and <pb-view> are three web components
from \texttt{pb-components} library, while <main> is a standard HTML5 tag. The
name of the custom element \TeiEmphasisI{must} start with a prefix to
distinguish it from standard HTML. This concept should be familiar to XML people. For TEI
Publisher components, the prefix is always \texttt{pb-}. Components from other sources
will use different prefixes, e.g. \texttt{paper-} and \texttt{iron-} for the
\TeiEmphasisII{ Polymer} collection. 

The part of the page which uses TEI Publisher web components should always be wrapped
into an <pb-page> element. This element determines the TEI Publisher server
instance all other components will be communicating with (see the next section below). It is
also responsible for some other initialization steps, e.g. loading the list of available
user interface translations. . 

<pb-document> specifies a document source, which can then be referenced by id from
other components. The component provides a way to configure basic properties governing
document's default rendering, like associated ODD file, etc. In the example above, we define
three properties for each document: 

\begin{description}
\item [path] 
the relative path to the XML document. This will be interpreted as relative to
the \TeiEmphasisII{data root collection} of TEI Publisher, by default pointing to
the data collection within the TEI Publisher app. 

\end{description}
\begin{description}
\item [odd] 
the name - without suffix - of the ODD to use for rendering the document. In the
example, the first document is encoded in TEI and thus transformed through 
dta.odd, while the second is written in DocBook and passed through
docbook.odd. 

\end{description}
\begin{description}
\item [view] 
this property determines how the document will be paginated if the user navigates
forward/backward. Currently three possible methods are available:

\begin{enumerate}
\item {

div : displays one structural division (TEI div, DocBook
section …) at a time 

}\item {

page : displays the document page by page. This requires
page break indicators to be present (<pb> in TEI, not supported for
docbook). 

}\item {

single : the entire document (or a selected fragment of it)
is displayed at once 

}\end{enumerate}

\end{description}

<pb-view> is the critical component in TEI Publisher: it provides the actual text
view by transforming a part or entirety of the source XML into HTML based on the processing
model instructions in the ODD. 

Because webcomponents are all about encapsulation, <pb-view> ensures that the
styling of the text as governed by the ODD will be confined to the boundaries of the
component. This makes it possible to display two completely heterogenous texts (like the
documentation and Kant's Kritik) on the same page without styles contaminating each other.
As a downside, encapsulation also poses some challenges, which we discussed in the section
about CSS styling. 

\subsection*{Webcomponent Documentation}

\label{webcomponents-docs}
To better understand the various components TEI Publisher provides, it is best to have
a look at the small examples contained in the \href{https://cdn.tei-publisher.com/api.html}{web components API
documentation}. The list of components may be overwhelming at first sight. However
you don’t need to learn them all. There are just a few components that should be understood
before you start customizing. Their demo pages showcase a working example along with the
code snippet which actually implements it. 

You can also get an editable live view like the one above if you click on the
Edit Code button to the bottom right of each example. 

In particular you may want to look at the following examples:

\begin{description}
\item [
\href{https://cdn.tei-publisher.com/api.html#pb-document.1}{ pb-document}
] 
shows the example given above in action

\item [
\href{https://cdn.tei-publisher.com/api.html#pb-view.1}{
pb-view}
] 
adds navigation buttons to read the document page by page

\item [
\href{https://cdn.tei-publisher.com/api.html#pb-facsimile.1}{
pb-facsimile}
] 
display facsimiles via IIIF server and link to them

\item [
\href{https://cdn.tei-publisher.com/api.html#pb-leaflet-map.1}{
pb-leaflet-map}
] 
show a map and link to geo coordinates

\item [
\href{https://cdn.tei-publisher.com/api.html#pb-load.1}{
pb-load}
] 
call a server-side XQuery to retrieve additional information about the document,
in this case actors appearing in the play

\item [
\href{https://cdn.tei-publisher.com/api.html#pb-search.1}{
pb-search}
] 
execute a search on the database, retrieve the results and paginate through
them

\item [
\href{https://cdn.tei-publisher.com/api.html#pb-grid.1}{
pb-grid}
] 
dynamically add more columns to a horizontal grid of components

\end{description}
\begin{mdframed}[frametitle={\paragraph*{Caveat}

}]
Some properties of pb-view and other components are boolean properties. In HTML5 this
corresponds to an attribute without value, which is illegal in XML. If you want to
preserve valid XML, just write the attribute with the same name and value, e.g. \texttt{
append-footnotes="append-footnotes"}. 

\end{mdframed}

\subsection*{Communication between Components}

\label{webcomponents-communication}
To allow for maximum flexibility, nearly all of the TEI Publisher webcomponents
communicate via events: this way avoids hard wiring and components may appear anywhere on
the page. For example, the controls for paginating through a document do not directly talk
to the document view: they just send an \TeiEmphasisII{event}, indicating the users'
wish to navigate backward or forward. Components listening for this event may then react to
it by refreshing the text being displayed. 

Since you can have multiple text views showing content from different sources, every
event can be announced at a specific communication \TeiEmphasisII{channel}. This allows
us to distinguish between different sources, e.g. two transcriptions being shown side by
side. Most TEI Publisher components therefore accept two properties to configure the channel
they are listening or sending events to: 

\begin{description}
\item [subscribe] 
name of the channel to which this component subscribes to. It will only react to
events coming in via this channel.

\item [emit] 
name of the channel to which this components sends events.

\end{description}
If neither of these properties is given, the component will subscribe and emit to the
global default channel. A component may also send to a different channel than it subscribes
to, allowing chains of events.

Common properties and methods accepted by many TEI Publisher components are defined in
the class PbMixin.

\subsection*{Page Templates}

\label{webcomponents-page-templates}
TEI Publisher currently includes several different page templates, which combine the
building blocks described above with off-the-shelf components to achieve a certain page
layout and composition. If you look at the HTML code, you'll see a mix of
pb- elements and app-,
paper-, iron- elements. The last three
belong to the \TeiEmphasisII{Polymer} collection and you can find them documented in
the public \href{https://www.webcomponents.org/}{webcomponent registry}.
TEI Publisher components are not yet available there, though we may move some of the general
purpose components there later. 

To avoid redundancy, the page template files use eXist's templating feature to drag in
some repeating parts which are the same for all pages, for example, the toolbar and the
menu. You'll find these files in the corresponding sub-collection:

\begin{lstlisting}
<app-toolbar data-template="lib:include" data-template-path="templates/menu.html"/>
<app-toolbar data-template="lib:include" data-template-path="templates/toolbar.html"/>
\end{lstlisting} 
The following page templates are currently available in TEI Publisher:

\begin{description}
\item [
\href{templates/pages/view.html}{view.html}
] 
the default template showing a single text view at the center

\item [
\href{templates/pages/facsimile.html}{facsimile.html}
] 
a template featuring a facsimile view to the right, retrieving images from a IIIF
server

\item [
\href{templates/pages/letter.html}{letter.html}
] 
used for Graves' letter, this template displays an additional map to the right and
a list of places, people and organizations

\item [
\href{templates/pages/translation.html}{translation.html}
] 
shows a transcription and its translation side by side. Both are contained in the
same TEI document and extracted via an XPath expression passed to <pb-view>

\item [
\href{templates/pages/cortez-with-translation.html}{
cortez-with-translation.html}
] 
similar to translation.html but the alignment between
transcription and translation is more complex as the translation contains no page
breaks. The part of the translation corresponding to a given fragment of the
transcription thus needs to be computed dynamically for each page, using an XQuery
function (defined by the map on <pb-view>. 

\item [
\href{templates/pages/cortez}{cortez.html}
] 
like above but with additional facsimile panel

\item [
\href{templates/pages/vangogh.html}{vangogh.html}
] 
demonstrates three columns by default: a metadata column, a transcription which
can be switched to a diplomatic view including line endings, and a translation. Other
columns, e.g. facsimile or commentary can be added dynamically.

\item [
\href{templates/pages/dantiscus.html}{dantiscus.html}
] 
builds upon \texttt{facsimile.html} adding a collapsible
\texttt{pb-drawer} element to display metadata from
\TeiEmphasisII{teiHeader} section. 

\item [
\href{templates/pages/osinski.html}{osinski.html}
] 
similarly builds upon \texttt{facsimile.html} but a collapsible metadata
section is realized with a \texttt{pb-collapse} element. 

\end{description}
\begin{mdframed}[frametitle={\paragraph*{Important Note}

}]
The page templates are meant as examples to be copied and modified by users. They were
written to match the concrete example and do not intend to be universal. TEI is too
heterogenous to provide a one-size-fits-all solution. We thus believe that providing a
wide range of practical examples is the best way to help users realize their own
project.

Only the generic template, view.html should work with all
example TEI documents. 

\end{mdframed}

\subsection*{Create your own Template}

\label{customizing-page-template}
To create your own template

\begin{enumerate}
\item {
open one of the existing templates in e.g. eXide (by clicking the links in the list
above)

}\item {
adjust \texttt{content} attribute in \texttt{meta} tag to a label that fits
your template 

\begin{lstlisting}[language=html]

<meta name="description" content="XYZ edition project" />

\end{lstlisting} 

}\item {
save the file under a different name into the same collection (
templates/pages) 

}\end{enumerate}

Now reload the document you'd like the template to apply to and you'll be able to switch
to your new template, either by

\begin{itemize}
\item {
using the Template dropdown in the
Settings panel 

}\item {
adding a parameter template=mytemplate.html to the URL
showed by the browser 

}\item {
adding a processing instruction to a TEI document
to make a specific template the default: 

\begin{lstlisting}[language=html]
<?teipublisher template="translation.html" odd="dantiscus.odd" view="page"?>
\end{lstlisting} 

}\end{itemize}

\subsection*{Handling Complex Alignments}

\label{alignment}
It is often desirable to show two or more views of a document at the same time, for
example to display the translation aligned with a given source fragment. In the simplest
case, the transcription and translation may be aligned on the level of divisions or page
breaks and one can simply use two <pb-view> referencing different starting points
in the TEI document (this approach is implemented by the \href{templates/pages/translation.html}{translation.html}
template for Serafin's letter). 

Unfortunately things are not always as simple as that. For example, even if the
transcription contains page breaks or milestones which can be used to display a single page,
the translation might not. One thus needs a different approach to compute the alignment
between fragments. Nevertheless, the logic of the alignment algorithm will highly depend on
the conventions used in the encoding. TEI allows a wide variety of alignment mechanisms and
we do not want to limit the freedom of the editor by prescribing a particular method.

TEI Publisher thus implements a generic way to plug an XQuery function into the
processing pipeline. The function takes the source element being processed as input and may
replace it by its aligned equivalent. Such an equivalent may be another element or fragment
from the same or a different document. The source element will usually point to the part of
the transcription being displayed. The mapping function uses this as starting point to
determine an aligned fragment and returns it. The returned fragment will then be further
passed through the processing model.

The XQuery mapping function should be defined in the module
modules/map.xql. It takes an element as its only argument and may
return any valid TEI fragment, which will become the input for futher processing through the
processing model. 

The local name of the mapping function can then be supplied in the attribute
map of <pb-view>. As an illustration, the Van Gogh
example includes the following \texttt{pb-view} for displaying the translation: 

\begin{lstlisting}
<pb-view src="document1" map="vg-translation" xpath="//div[@type='original']"
subscribe="transcription"/>
\end{lstlisting} 
In the Van Gogh letters, the translation contains page breaks corresponding to page
breaks in the original letter, but these are using a different prefix for the
\texttt{xml:id}. To align the translation with the transcription, we only need to
adjust the id, and retrieve the corresponding page break to be done. The XQuery mapping
function is thus rather simple: 

\begin{lstlisting}
declare function mapping:vg-translation($root as element()) {
let $id := ``[pb-trans-`{$root/@f}`-`{$root/@n}`]``
let $node := root($root)/id($id)
return
$node
};
\end{lstlisting} 
Note that returning the corresponding <pb> node of the translation is
sufficient here as further processing will automatically extract the page fragment up to the
next <pb>. More complex cases may require that mapping function returns arbitrary
TEI fragment. Also note that the xpath attribute of the
<pb-view> element in the template must still point to the source transcription (
div[@type='original'] in this case). It's just the mapping
function which translates a position in the source transcription to a corresponding fragment
in the translation. 

The letter by Cortez to Dantiscus sent from Mexico demonstrates a much more
sophisticated alignment, determining the translation fragment to be shown by inspecting the
ID range of the transcription. It illustrates the case where no milestone elements exist in
the translation to explicitly mark page boundaries of the original, thus mapping algorithm
aims to display closest corresponding fragment of the translated text.

\subsection*{Facsimiles and other images}

\label{facsimiles}
While you can use the graphic behaviour in the ODD to embed simple images, high-resolution images will usually be served by a separate IIIF service (running outside eXist/TEI Publisher). As of version 8.1.0 of TEI Publisher, two web components are available to handle images provided via the IIIF protocol:

\begin{description}
\item [pb-facsimile] 
A viewer implementing the IIIF image API for viewing one or more images. The names/paths of those images need to be known beforehand and should be registered with the component via <pb-facs-link> or custom javascript. The viewer is based on \href{https://openseadragon.github.io/}{OpenSeadragon}.

\item [pb-tify] 
Supports IIIF presentation manifests: instead of registering a list of images, it expects all relevant metadata - including the list of images - to be provided in a single, standardized manifest. Under the hood, <pb-tify> is based on \href{https://tify.rocks/}{tify}, which also uses \href{https://openseadragon.github.io/}{OpenSeadragon} for the image display functionality. Available since version 2.10.0 of tei-publisher-components.

\end{description}

\subsubsection*{Passing the list of images to <pb-facsimile>}

\label{passing-facsimiles}
Usually the facsimiles to be shown are registered with <pb-facsimile> by outputting a <pb-facs-link> web component via the ODD. In most cases this is done when processing a TEI <pb> or <surface>. The name of the image will be taken from the @facs attribute and copied to the <pb-facs-link>. To resolve the full API link, <pb-facsimile> prepends the base-uri configured on it. However, you can also specify an absolute URL on the <pb-facs-link>. Read more about troubleshooting IIIF links in the \href{https://faq.teipublisher.com/images/image-endpoints/}{FAQ}.

\subsubsection*{Using IIIF presentation manifests}

\label{presentation-manifests}
A IIIF presentation manifest is a JSON structure describing a collection of resources. <pb-tify> expects to load a single manifest and takes all necessary information from there. If you have an external image database, it may already be able to deliver a manifest. If not, you can easily generate one on the fly by creating an API endpoint. This approach is demonstrated by the Shakespeare example in TEI Publisher, which proceeds as follows:

\begin{enumerate}
\item {
\url{modules/custom-api.json} defines an endpoint /api/iiif/\{path\} and the corresponding handler in modules/iiif.xql, function iiif:manifest. The path parameter is expected to point to an existing TEI document.

}\item {
The XQuery code in function iiif:canvases walks through each <pb> element in the TEI to output a IIIF canvas for the linked image.

}\item {Function iiif:manifest adds additional metadata fields like title, language or download links to the manifest.

}\item {
\url{templates/pages/shakespeare.html} includes the <pb-tify> web component, pointing it to the custom API endpoint:

\begin{lstlisting}[language=xml]
<pb-tify subscribe="transcription" emit="transcription" manifest="api/iiif/${docid}" 
data-template="pages:parse-params"></pb-tify>
\end{lstlisting} 

}\end{enumerate}

The manifest to be loaded can either be specified via the @manifest attribute on the <pb-tify> component, or it may be
provided dynamically via <pb-facs-link> elements elsewhere on the page or in content generated by an ODD. In this case the
@facs attribute of <pb-facs-link> should contain the URL to the manifest rather than a single IIIF image.

Switching to a specific page can also be done via <pb-facs-link>: the @order attribute is interpreted as a page number
(starting with 1) and <pb-tify> will show the corresponding image when <pb-facs-link> is triggered, i.e. the user moves the mouse
over or clicks the element (the @trigger attribute takes the values "mouseover" or "click"). If you would like a
<pb-facs-link> to trigger manifest or page loading upon load, specify the boolean attribute @emit-on-load. The Shakespeare
example does load the correct manifest in this way, i.e. by outputting a <pb-facs-link> through the ODD, using @manifest and
@order to select the page currently shown in the transcription.

\subsubsection*{Customizing the generated manifest}

\label{presentation-manifest-config}
The way in which facsimile images are referenced from a TEI document will differ between projects. We
nevertheless tried to keep the code as generic as possible, but there are a few settings which may need
adjustment.

All settings concerning IIIF manifest generation can be found in
modules/iiif-config.xqm. In particular, you may want to change the following
variables/functions:

\begin{description}
\item [\$iiifc:IMAGE\textunderscore API\textunderscore BASE] 
The base URI of the IIIF image service to use for displaying images

\item [iiifc:milestones] 
Should return the TEI elements in the document context which reference an image. Usually those are
<pb> or <milestone> elements, but other variations are possible.

\item [iiifc:milestone-id] 
For each element returned by \texttt{iiifc:milestones}, extract the path to the image. By default this
tries to read the image path from the @facs attribute.

\end{description}

\section*{Server-side API}\markboth{Server-side API}{Server-side API}

\label{api}
Many of the user interface web components need to communicate with the server to request
certain data to be retrieved, processed and returned before the client-side components can
display it to the user. For example, when user clicks the Table of
Contents button, the corresponding pb-load component
sends an ajax request to retrieve the list of chapters. Similarly, when user types something
in the autocomplete field, a request is sent after each keystroke to find matching terms in
the index. These requests need to be received and processed by the server with the eXist
instance running and only then data will be returned to the browser. 

Previous versions of TEI Publisher included a number of XQuery modules implementing
the server-side functionality, located in modules collection. In
version 7, a new approach has been introduced. A formal \href{../api.html}{API specification}, based on the \href{http://spec.openapis.org/oas/v3.0.3}{Open API standard}, defines all the
server-side API endpoints available in Publisher. The library responsible for interpreting the Open API specification 
and routing requests to XQuery endpoints is called \href{https://github.com/eeditiones/roaster}{roaster}
and can also be used outside TEI Publisher.

The image below presents a section of the API handling all ODD-related operations:
creating, retrieving, updating, deleting, recompiling; syntax check for a code fragment
(lint); retrieving a list of all available ODDs.

\begin{figure}[h]
\caption{TEI Publisher API page - the odd endpoint}

\includegraphics[max size={\textwidth}{\textheight}]{api-spec.png}

\end{figure}

\subsection*{Advantages of the API-based approach}

\label{api-advantages}
\begin{itemize}
\item {

\TeiEmphasisI{clear specification and easy overview}

users and developers will benefit from the clear specification for available
functionality

}\item {

\TeiEmphasisI{customizable}

users can easily overwrite and extend existing API endpoints as well as add custom
ones for project-specific functionality

}\item {

\TeiEmphasisI{separation of concerns}

server-side functionality can be used directly by any software system, not
necessarily within the context of the TEI Publisher or using Publisher's UI components;
further changes in internal API implementation do not require any adjustments of the UI
components

}\item {

\TeiEmphasisI{standard-based}

OAS compliance means we are using a well-known and documented standard and can
benefit from existing tools for writing, testing and generating documentation

}\end{itemize}

\subsection*{API endpoint groups}

\label{api-endpoints}
TEI Publisher 7 groups server-side functionality into several main sections:

\begin{description}
\item [documents] 
Retrieve entire or part of a document content transformed to a target format;
retrieve document's table of contents; delete a document.

\item [collection] 
Browse the collection hierarchy and upload new files.

\item [odd] 
Manage the ODD files stored in TEI Publisher: create, retrieve, update, delete,
recompile; check syntax for a code fragment (lint); retrieve a list of available
ODDs.

\item [search] 
Search: run a search through collections; list facets for the search results; list
autocomplete options.

\item [transform] 
Transform content on the fly: convert a Word document to TEI or POST an XML
document and get its preview rendered via ODD.

\item [view] 
View documents via an HTML template; list available templates.

\item [apps] 
Operations for managing apps: generate a standalone application or package and
download an app.

\item [dts] 
Implementation of the DTS (Distributed Text Services) API.

\item [user] 
Login: authorize the user.

\item [info] 
Information about the server: the API version.

\end{description}

\subsection*{Custom API endpoints}

\label{api-custom-endpoints}
Beyond the standard server-side functionality provided by TEI Publisher, careful
provisions have been made to allow users to add their own API endpoints. The \href{../api.html#operations-tag-default}{Custom API} section
demonstrates how project-specific functionality can be added within the OAS API scheme. 

All that is required is to edit the \url{modules/custom-api.json} file
and add specifications for custom endpoints in JSON format. The
operationId property specifies the XQuery function to be called to
process the request. All function modules with API functions need to be imported
into \url{modules/custom-api.xql} so that the request can be correctly
resolved. 

The function implementation can either be added to the XQuery module 
modules/custom-api.xql or to a new module, which should be imported into this
file to make it known. The modules/custom-api.xql shipping with TEI Publisher already 
includes one custom endpoint used for the \href{../encyclopedia}{"Damen Conversations Lexikon"}: it returns a JSON structure for consumption
by <pb-split-list>, displaying the list of available lemmata in the encyclopedia.

In addition, it imports a separate module from \url{modules/iiif.xql}, containing functions for
generating a IIIF presentation manifest (see the \href{../test/F-rom.xml}{Shakespeare example}):

\begin{lstlisting}
import module namespace iiif="https://e-editiones.org/api/iiif" at "iiif.xql";
\end{lstlisting} 
To reference a custom function in the operationId parameter of
modules/custom-api.json, use the prefix custom: if the corresponding XQuery
function is available in modules/custom-api.xql. If it resides in an imported module, use
the prefix defined for the import. For the IIIF module import above, this would be iiif, so the operationId
would read:

\begin{lstlisting}
"operationId": "iiif:manifest",
\end{lstlisting} 

To learn more about the Open API functionality supported by roaster and the different fields and parameters available through
the passed in \texttt{\$request} parameter, see the \href{https://github.com/eeditiones/roaster}{README} of \TeiEmphasisII{roaster}.

\section*{URL Routing}\markboth{URL Routing}{URL Routing}

\label{url-routing}

\subsection*{Creating custom URLs}

\label{custom-urls}
By default, TEI Publisher addresses the different example pages by the name of the XML document displayed, which means users will see
the relative path to the document in the URL. A request to \texttt{/test/adagia.xml} will be handled by the Open API route matching the 
path \texttt{"/\{docid\}"}, which then calls the XQuery function vapi:view to retrieve the HTML template 
associated with the TEI document and return it to the browser:

\begin{lstlisting}

"/{docid}": {
	"get": {
		"summary": "Retrieve the HTML template used for displaying a document",
		"description": "Get the HTML template associated with the given document. This is called whenever the users tries to view a document. The actual content of the document will then be loaded by the template.",
		"tags": ["view"],
		"operationId": "vapi:view",
		"x-error-handler": "vapi:handle-error",
		...
	}
}

\end{lstlisting} 
Addressing by relative path is convenient for a heterogenous collection like the one in TEI Publisher, but for a more homogenous
edition, you may prefer other addressing schemes, e.g. using an identifier. For example, the Alfred Escher Briefedition uses URLs like 
\url{https://briefedition.alfred-escher.ch/briefe/B0017}. Using an abstract identifier has the advantage that bookmarked URLs
remain accessible even if the implementation changes (as happened for Escher), given that the identifier is stable. An even more complex addressing scheme can be found in the \href{https://www.johannconradfischer.com}{Johann Conrad Fischer} edition. Here the different travel journals are addressed by the year they cover, and the chapter to show is given as a number. Additionally, the language is given in the first path parameter, so the resulting URLs have the form: \texttt{/language/year/chapter}, e.g. \texttt{/de/1794/9}. Obviously implementing a scheme like this requires a bit more tweaking, so we'll concentrate on simpler cases like the one in Escher.

TEI Publisher includes two examples, which deviate from the default addressing scheme:

\begin{description}
\item [TEI Publisher documentation] The entire documentation is contained in one file. Users may want to copy or bookmark a specific section, whose identifier is thus encoded in the URL using a scheme \texttt{/documentation/\{identifier\}}.

\item [\href{../encyclopedia}{Damen Conversations Lexikon}] 
An early 19th century encyclopedia in German. An encyclopedia or dictionary is usually not read page by page. Instead users will want to browse to a particular headword they are interested in. Accordingly, the URL should reflect the chosen headword rather than the document. URLs are thus of the form \texttt{/encyclopedia/\{headword\}}.

\end{description}
Both examples need two route definitions: the first corresponding to the root page displayed, i.e. if the user has not selected a chapter or headword, the second to represent the detail view of a chapter or headword. For the documentation, \url{modules/custom-api.json} thus has configurations for \texttt{/documentation} as well as \texttt{/documentation/\{id\}}. In both cases we simply copied and modified the configuration for the standard path, i.e. \texttt{"/\{docid\}"}, from \url{modules/lib/api.json}.

The default endpoint takes various parameter, including two required ones: docid for the path to the TEI document, and template to specify the HTML template to use. For the documentation those will always be the same, i.e. doc/documentation.xml and pages/documentation.html, so we can pass them as a default value. This way we can reuse the existing operation (vapi:view) and don't have to write a custom handler function in XQuery!

We also add two parameters, id and base. The first will take the xml:id of the chapter we're looking for. id is one of the standard parameters picked up by the <pb-view> in the HTML when loading the actual content to display. base will be used in the template to set the HTML <base> tag in the HTML head. This is required to tell the browser where images and other resources should be loaded from:

\begin{lstlisting}[language=html]
<head>
<base href="${base}" data-template="pages:parse-params"/>
...
</head>
\end{lstlisting} 
The complete definition of the route in \url{modules/custom-api.json} looks like this:

\begin{lstlisting}

"/documentation/{id}": {
"get": {
"summary": "Select the HTML template for viewing the documentation",
"description": "Shows a particular chapter as indicated by the id",
"tags": ["documentation"],
"operationId": "vapi:view",
"x-error-handler": "vapi:handle-error",
"parameters": [
{
"name": "id",
"in": "path",
"required": true,
"schema": {
"type": "string"
}
},
{
				"name": "template",
				"in": "query",
				"schema": {
						"type": "string",
"default": "pages/documentation.html"
					  }
					},
{
"name": "docid",
"in": "query",
"schema": {
"type": "string",
"default": "doc/documentation.xml"
}
},
{
"name": "base",
"in": "query",
"schema": {
"type": "string",
"default": "../doc/documentation.xml"
}
}
],
"responses": {
"200": {
"description": "HTML template for documentation",
"content": {
"text/html": {
"schema": {
"type": "string"
}
}
}
}
}
}
}
\end{lstlisting} 
This handles the server-side routing of requests. However, there's also a client-side aspect, which we'll cover in the next chapter.

\subsection*{Adjusting the client-side URL handling}

\label{client-side-urls}
With the two routes we set up for the documentation in the previous section, we cover the cases in which the entire page is loaded or reloaded by the browser, either by following a link, selecting a bookmark or pasting an URL into the location bar. However, TEI Publisher is a highly dynamic application and users can interact with the page without reloading it, e.g. by navigating to the next page of the document, selecting a toggle, clickling a link in the table of contents etc. Client-side interactions like this also need to be recorded and should be reflected in the URL, so users can copy or bookmark it. And the bookmarked link should later reconstitute the page in the state it was in when the bookmark was created.

All client-side web components in TEI Publisher therefore use a central state registry to track their state and reflect it in the URL. You can see this in action when you open any of the larger sample documents and navigate between its pages using the navigation buttons: the URL shown in the browser's location bar will change. For simple documents like \href{../test/kant_rvernunft_1781.TEI-P5.xml}{Kant's Kritik}, the current page displayed will be encoded in the root parameter. If the divisions or pages to navigate by have an \texttt{xml:id}, this will be used instead and placed into the id parameter. The path to the TEI document is also tracked (it's the \texttt{test/kant\textunderscore rvernunft\textunderscore 1781.TEI-P5.xml} part of the URL), though you won't see it change while navigating.

For the documentation we deviate from this default pattern with the relative URL becoming \texttt{documentation/\{id\}}. We thus need to inform the client-side components about the change, so they know how to store their state into the URL. The central <pb-page> component provides two attributes for this:

\begin{description}
\item [url-template] 
A template expression containing placeholders for the parameters to be filled in. The template uses the same syntax and library as the popular \href{https://expressjs.com/en/guide/routing.html#route-paths}{Express javascript framework}.

\item [url-ignore] 
A comma-separated list of parameter names which should \TeiEmphasisII{not} be reflected in the URL.

\end{description}
The expression passed to url-template may reference any of the default parameters known to TEI Publisher components, in particular path, odd, view or id. Additionally, any parameter supplied to a <pb-view> via the <pb-param> element can be referenced. Just have a look at the constructed URLs in the browser to see which parameters are being tracked for a specific page. Within TEI Publisher, URL templates will usually be rather simple. For the full syntax supported check the underlying \href{https://www.npmjs.com/package/path-to-regexp}{javascript library}.

To handle the URL for the documentation example, we set the URL template to \texttt{documentation/:id?}. This injects the id parameter as part of the path, e.g. \texttt{/documentation/api}. The ? after the parameter indicates that it is optional. We also do not want the \texttt{path} to the document to appear anywhere (it is always the same in the case), so we add it to \texttt{url-ignore}. The resulting <pb-page> would thus look as follows:

\begin{lstlisting}[language=html]
<pb-page url-template="documentation/:id?" url-ignore="odd,view,path" data-template="pages:pb-page" unresolved="unresolved" >
\end{lstlisting} 
\begin{mdframed}[frametitle={\paragraph*{A note on history handling}

}]
It is important that only one central text component on the page writes and reads the URL. Usually this will be the main <pb-view>. Other components, e.g. for the translation, should be made dependent and restore their state based on the state of the main component. If multiple components write their state, browsing back via the browser history may not work properly, or you may see undesired effects due to conflicting parameters.

TEI Publisher supports different ways to make one <pb-view> depend on another, e.g. via a mapping function (map attribute). A mapped view will never write to the browser history.

In other cases, to explicitely prevent a dependent <pb-view> from writing to the URL, use the attribute disable-history. To make a <pb-view> load its contents \TeiEmphasisII{after} the main text view, set attribute on-update and make sure, the dependent component listens to the event channel written by the main component.

\end{mdframed}

\section*{Language versions}\markboth{Language versions}{Language versions}

\label{i18n}
TEI Publisher is already available in twenty languages and this number increases thanks to
the engagement of our user community.

With version 6.0 i18n support has been greatly extended to cover not only labels and
attribute values in HTML templates but also within web components. A mechanism for project
specific language files extending the default Publisher label collection has been
added.

Thanks to community contributions via \href{https://crwd.in/tei-publisher}{
Crowdin} a number of languages has been added and existing ones are updated when
needed. We welcome and encourage additions and amendments. Please consider Crowdin a master
repository for translations and publish your contributions there instead of submitting PR
directly. Do not hesitate to get in touch if a language you'd like to support is not yet
listed. 

Crowdin users are only exposed to form-based graphical user interface but i18n files are
using JSON format to preserve their logical structure. Initial portion of German localization
file de.json is shown below for illustration. 

\begin{figure}[h]
\caption{Translation JSON file structure}

\includegraphics[max size={\textwidth}{\textheight}]{i18n-json-structure.png}

\end{figure}

In TEI Publisher and in generated apps translation files are by default loaded from CDN
with \texttt{pb-components}. When it is necessary for a project to add new labels or
change wording of existing ones, a customization mechanism is described below. 

\subsection*{Using i18n in page templates}

\label{i18n-page-templates}
There are several scenarios for using i18n labels:

\begin{itemize}
\item {
directly within HTML element

}\item {
in an attribute

}\item {
passed in component-specific structure

}\end{itemize}

\subsubsection*{ HTML text node with \texttt{pb-i18n}
}

\label{i18n-page-templates-pb-i18n}
Any text fragment within HTML element can be considered a target for i18n when
wrapped in <pb-i18n> component. <pb-i18n> elements are listening for
events emitted by <pb-lang>. 

\begin{lstlisting}[language=html]

<h3 slot="collapse-trigger">
<pb-i18n key="menu.documentation">Documentation</pb-i18n>
</h3>

\end{lstlisting} 

\subsubsection*{Attributes (on HTML elements or custom web components)}

\label{i18n-page-templates-attributes}
When it is necessary to translate the value of an attribute a mechanism based on
\texttt{ data-} attributes is used. Supply additional \texttt{data-i18n}
attribute specifying the key of the i18n label to use preceded by the name of the
attribute that needs to be translated. In the example below it's the \texttt{heading}
attribute that needs to be filled with the translated version of \TeiEmphasisII{ODD
Files} label. The label is stored in JSON file under \texttt{odd.files},
so \texttt{ [heading]odd.files} needs to be used for the \texttt{data-i18n}
attribute. 

\begin{lstlisting}[language=xml]

<paper-card data-i18n="[heading]odd.files" class="odds" heading="ODD Files">
<div class="card-content"> ... content of the ODD list </div>
</paper-card>

\end{lstlisting} 
When <pb-lang> is switched to Spanish, the <paper-card> heading
will read \TeiEmphasisII{Archivos ODD} instead of \TeiEmphasisII{ODD Files}. 

\begin{figure}[h]
\caption{ Output for <paper-card> with translated \texttt{@heading}
}

\includegraphics[max size={\textwidth}{\textheight}]{i18n-attribute.png}

\end{figure}

\subsubsection*{Special web component properties configured via attributes}

\label{i18n-page-templates-properties}
Some web components accept more complex configuration options via arrays passed in
attributes. For example, <pb-browse-docs> component allows to specify a number of
label/value pairs for dropdown menus used for ordering and filtering the document list.
Understandably, the labels should switch in line with changes to the language chosen via
< pb-lang>. Therefore i18n translation keys like
\TeiEmphasisII{browse.title} or \TeiEmphasisII{ browse.author} are used
instead of text values. Note that web components may have particular expectations for the
data format expected so consult API documentation for each component. 

\begin{lstlisting}[language=html]

<pb-browse-docs id="document-list" url="collection/" 
sort-options='[{"label": "browse.title", "value": "title"},{"label": "browse.author", "value": "author"}]' 
sort-by="title"
filter-options='[{"label": "browse.title", "value": "title"},{"label": "browse.author", "value": "author"},{"label": "browse.file", "value": "file"}]' 
filter-by="title" 
auto="auto" history="history" login="login" emit="docs" subscribe="docs">
<pb-paginate slot="toolbar" id="paginate" per-page="10" range="5" emit="docs" subscribe="docs"></pb-paginate>
</pb-browse-docs>

\end{lstlisting} 

\subsection*{Project specific i18n files}

\label{i18n-customization}
It is a common need that projects will need their own internationalized labels for menu
items, dialogs and other user interface elements.

All these can be stored in JSON language files, following the same naming conventions
and basic structure as TEI Publisher ones. To use custom language files, you need to specify
the path under which they can be found relative to your application:

\begin{lstlisting}[language=html]
<pb-page locales="resources/i18n/{{ns}}/{{lng}}.json">
\end{lstlisting} 
The path expression requires placeholders for two parameters ns
and lng : 

\begin{description}
\item [lng] 
the language code for a selected language, e.g. \texttt{de} or
\texttt{fr}

\item [ns] 
the namespace prefix used to distinguish between different collections of
language files. By default, TEI Publisher expects custom language files to be in a
namespace called \texttt{app}, though this can be configured. 

\end{description}
So given above configuration, TEI Publisher will search for a custom language file for,
say, French in \texttt{resources/i18n/app/fr.json}. If you prefer a flat directory
structure, you could change the locale to \texttt{
resources/i18n/\{\{ns\}\}\textunderscore \{\{lng\}\}.json} and TEI Publisher will look for a file \texttt{
resources/i18n/app\textunderscore fr.json}. 

You may also define additional namespaces to be searched with the 
locale-fallback-ns parameter: 

\begin{lstlisting}[language=html]
<pb-page locales="resources/i18n/{{ns}}/{{lng}}.json"
locale-fallback-ns="app my-module">
\end{lstlisting} 
which means that TEI Publisher will search for labels in the \texttt{my-module}
namespace first, then falling back to the \texttt{app} namespace, and if the label could
still not be found, using TEI Publisher's default namespace. The latter is called \texttt{
common} and should not be overwritten. 

Listing below demonstrates a fictional en.js with a custom set of
labels. A new top-level key has been added as well as 3 subkeys for the \texttt{menu}
section. Now the project has access to a number of new i18n keys: \texttt{menu.about},
\texttt{ menu.contact}, \texttt{menu.statute} and \texttt{greeting}. 

Furthermore, a value for \texttt{menu.documentation} has been specified. That key
already existed in Publisher (set to "Documentation") but the version from custom file will
take precedence and be used in the custom app. 

\begin{lstlisting}

{
"menu": {
"documentation": "Docu",
"about": "About",
"contact": "Contact",
"statute": "Statute"
},
"greeting": "Welcome"
}

\end{lstlisting} 

\section*{Creating applications with the App Generator}\markboth{Creating applications with the App Generator}{Creating applications with the App Generator}

\label{appgen}
Once you are happy with a certain ODD and HTML template customization, you can easily
create a complete, standalone application. Such application can be tailored further to fit
your needs. The generated app can be downloaded as a portable xar package, to be installed
into other eXist instances, or synchronised to disk for further development. It provides a
fully functional application scaffolding based on TEI Publisher components and modules,
pre-configured to use a certain ODD, page template and other settings.

\begin{mdframed}[frametitle={\paragraph*{Note}

}]
Early versions of the TEI Publisher included everything they needed to run without TEI
Publisher. This had some advantages, but also made it more difficult to update to newer
releases.

Starting with version 5 we are gradually moving towards more lightweight app design,
ultimately containing only resources which are truly specific to the app (ODDs, HTML
templates, images), while all generic functionality will be provided by TEI Publisher and
its libraries and packages. Version 6 has seen all web components extracted into \texttt{
pb-components} package and in version 7 the server-side code has been based on a
well designed API specification with provisions for easy customization.

Please make sure you are following our best
practice recommendations for a smooth upgrade path. 

\end{mdframed}
To get started, click on App Generator in the menu bar and
fill out the form. 

The following form fields are of particular importance:

\begin{description}
\item [ODD] 
Here you select the ODD(s) to be used for transformations. If multiple ODDs are
selected, the first one will be the default.

\item [URL to identify the app] 
This is the main identifier for your app and should be a globally unique URI. It
does not need to correspond to any existing web site. eXist's package manager is using
this URI as a unique identifier for the app.

\item [Abbreviation] 
The abbreviation will be used as the name of the root collection of your app and as
the last path component in any URL pointing to the app. It should be unique within one
database instance.

\item [Template] 
The HTML template to be used as default for viewing a document. If you created a
custom template or modified any of the existing templates, you likely want to select
this here.

\item [Data Collection] 
Only specify something here if you have existing data inside the database or if you
want to ship the data set as part of a second, separate app. In all other cases, leave
this field empty.

\item [Default View] 
Default document view - whole document, page by page or division by division. If
you would like to choose page by page, set this to "By Page"
but please note that all your documents must be appropriately encoded with page breaks
as <pb> elements. You will still be able to change the view settings in HTML
template or users can do it via query parameters. 

\item [User/Password] 
The user account which will own all application files. For security reasons, it is
advisable to create a new account for every app.

\end{description}
Once you created the new application, log into it using the account details you provided.
You can then upload XML documents using the upload panel in the sidebar.

\subsection*{Generated Code Overview}

\label{appgen-code-overview}

\subsubsection*{XQuery Code}

\label{appgen-code-overview-xquery}
The collection structure of the generated app follows typical design of many eXist
apps. Best practices for modifying the
app are discussed in further sections of this document. You can find the code of your
generated app within the /db/apps collection under the name you
provided in the \TeiEmphasisII{abbreviation} field of the generator form. 

\begin{description}
\item [modules] 
Contains XQuery modules used by the app, including the copied TEI Publisher
libraries in modules/lib subcollection. 

\item [resources] 
Contains a number of subcollections for various resources used by the app, such
as images, fonts or JavaScript libraries. Of particular interest is the 
resources/odd subcollection where app's own ODD files are stored. 

All of the app styling is done via a set of modularized less stylesheets,
residing in resources/css. The main file is 
style.less, which defines a number of core parameters. Ideally this
should be the only file you ever need to modify. 

\item [templates] 
Html templates for the templating framework. Contain page templates as well as
smaller components such as menu or login pane.

\item [transform] 
This collections contains XQuery modules governing the transformations and
styles generated from app's ODD. Its content will be overwritten with each ODD
recompilation, thus there's no point modifying it. It's worth consulting though to
gain better understanding and troubleshoot the transformations with TEI Processing
Model. In case of an issue, it may help to know the files: 

\begin{description}
\item [\{myodd\}-web.xql] 
The transformation module generated for output mode "web".

\item [\{myodd\}-web-module.xql] 
Library module which calls the transformation module.

\item [\{myodd\}.css] 
CSS styles generated from the ODD.

\end{description}
Files start with the name of the odd and the output mode they belong to.

\end{description}

\subsection*{Modifying the App}

\label{appgen-modify}
When you are logged in, the Admin menu in the top navbar
provides various links for ease of customization of your app: 

\begin{description}
\item [Recompile ODD] 
After changing the application's ODD, click here to update the app.

\item [Edit ODD] 
Opens the application's ODD in eXide for editing.

\end{description}

\subsubsection*{Using Multiple ODDs}

\label{multiple-odds}

For performance reasons, the mechanism used by generated apps to transform a document
via an ODD is slightly different to the one in the main TEI Publisher app: while TEI
Publisher resolves ODDs dynamically, generated apps use a static lookup method. 

The static method is much faster, resulting in better overall performance, but as a
consequence ODDs are not automatically detected by the app, and need to be explicitly
registered.

Each generated app will by default use a single ODD for all transformations but it is
possible to add additional ODDs, e.g. to be used with a \texttt{pb-view} in a custom
HTML template. If multiple ODDs are selected when generating the app, the app generator
will take care of registering those ODDs. If you would like to add ODDs manually later,
the procedure is as follows: 

\begin{enumerate}
\item {
Upload the ODD to the resources/odd collection below your
app root. This can either be done via \TeiEmphasisII{eXide} or the 
Upload panel on the start page of your app. 

}\item {
In modules/config.xqm find the variable called 
\$config:odd-available and add the name of the new ODD to the sequence. 

\begin{lstlisting}
(:~
: The main ODD to be used by default
:)
declare variable $config:default-odd :="shakespeare.odd";

(:~
: Complete list of ODD files used by the app. If you add another ODD to this list,
: make sure to run modules/generate-pm-config.xql to update the main configuration
: module for transformations (modules/pm-config.xql).
:)
declare variable $config:odd-available :=("shakespeare.odd");
\end{lstlisting} 

}\item {
In eXide, open modules/generate-pm-config.xql (path relative
to your app root) and execute it once. This will regenerate the XQuery module
modules/pm-config.xql, which registers all the ODD modules
known to the app. 

}\item {
Additionally you need to regenerate all ODDs used by the app by either

\begin{enumerate}
\item {
Clicking the Regenerate all ODDs button on the start
page of the app 

}\item {
Via the api documentation page api.html by executing the
POST version of the \texttt{/api/odd}. 

}\end{enumerate}

}\end{enumerate}

\paragraph*{Using different ODDs depending on the collection}

\label{multiple-odds-collection}
By default the same ODD will be used for all documents within the app. It is
possible though to organize documents into a hierarchy of
collections beneath \$config:data-root and use different
ODDs and general view settings for each collection or document type. 

To do so, search for the function config:collection-config,
which by default returns an empty sequence - meaning that the default configuration
should be used. Comment this out and enable the switch/case statement below to return a
different config depending on the current collection. The
\$collection and \$docUri parameters be
relative paths, i.e. relative to  \$config:data-root. So for a
single level hierarchy as used in TEI Publisher by default,
\$collection will be either \texttt{test}, \texttt{
playground} or \texttt{doc}. For multi-level hierarchies it might also be
e.g. \texttt{volume1/transcripts}. In this case a simple switch/case might not be
enough, but you can just replace it with an if/then/else and apply any path matching you
like. 

\begin{lstlisting}

declare function config:collection-config($collection as xs:string?, $docUri as xs:string?) {
(: Return empty sequence to use default config :)
()

(: 
: Replace line above with the following code to switch between different view configurations per collection.
: $collection corresponds to the relative collection path (i.e. after $config:data-root). 
:)
(:
switch ($collection)
case "playground" return
map {
"odd": "dodis.odd",
"view": "body",
"depth": $config:pagination-depth,
"fill": $config:pagination-fill,
"template": "facsimile.html"
}
default return
()
:)
};

\end{lstlisting} 
Instead of switching by collection, you could also configure different views
depending on the type of document, e.g. by checking the type of the first div: 

\begin{lstlisting}
doc($config:data-root || "/" || $docUri)//tei:body/tei:div/@type
\end{lstlisting} 

\subsection*{Exporting the Finished App}

\label{appgen-export}
To save your finished application or exchange it with other people, you need to save it
as an application archive. Application archives use a standardized \href{https://exist-db.org/exist/apps/doc/repo#expath-pkg}{EXPath Packaging}
format: the resulting .xar file can be uploaded to any eXist instance
via the Dashboard and the Package manager will
take care of the deployment. 

There are two ways to create a .xar file from your application: 

\begin{enumerate}
\item {
Use the Admin  / Download App menu
entry in generated app to directly download a .xar

}\item {
Synchronize the application to a directory on disk via
Application / Synchronize in \TeiEmphasisI{eXide}

}\end{enumerate}

The first approach is recommended if all you need is a copy of you app on disk. A
.xar is just a ZIP archive, so you can unpack it into a directory of
your choice, which you can then commit to a version control system like git. 

However, if you continue to make changes inside the database (e.g. further work on the
ODD), you may want to use the second method, i.e. call eXide's synchronization. It requires
that you have access to the file system of the server running eXist though, so it's usually
only an option if you run your own eXist instance locally. The synchronize steps in
detail:

\begin{itemize}
\item {
Prerequisite: you need to have the \href{http://ant.apache.org/}{Apache Ant} build tool installed. 

}\item {
Open one resource belonging to your application in eXide. It doesn't matter which
one. The only important thing is that the name of your app is displayed next to
Current app: on the top right of the eXide window. If this is
not the case, stop and check again! 

}\item {
Click Application / Synchronize in
the menu. It opens up a dialog with two fields: Start time and
Target directory. When you synchronize the first time, empty
the Start time field. Enter a valid, absolute directory path on
your server machine into Target directory. 

}\item {
Click the Synchronize button. This may take a moment, but
you should see a list of written files at the bottom of the dialog afterwards. 

}\item {
Change to the directory you specified for synchronize.

}\end{itemize}

Watch the screencast below for the whole synchronization procedure.

\begin{mdframed}[frametitle={\paragraph*{Note}

}]
for security reasons, the password you entered when creating the app is not stored in
the database, so it cannot be synchronized to disk. To restore a password for your app,
you thus need to edit the repo.xml file in the directory and add a
@password attribute to the <permissions> element.

\end{mdframed}

\subsection*{Building from a directory}

\label{appgen-build}
Once you have a copy of your app extracted in a local directory, you can always rebuild
a fresh .xar from it. In the simplest case it is sufficient to call
ant inside the directory. 

For up to date build instructions which also cover more advanced uses, refer to the
"Building" section in the \href{https://github.com/eeditiones/tei-publisher-app}{readme of the TEI Publisher repository}. 

\section*{Best Practice Recommendations}\markboth{Best Practice Recommendations}{Best Practice Recommendations}

\label{customization-best-practice}
In case you'd wish to further customize the generated app it's worth to keep the changes
as much separated from the generated code as possible to allow for future alignment with newer
versions of the TEI Publisher. 

The generated app shares most of its XQuery libraries with the main TEI Publisher app. A
copy of those is included in the lib/ collection of the generated app and
\TeiEmphasisI{should not} be modified! This way you can later update the
libraries to a newer TEI Publisher release without breaking your app. Including the libraries
in the generated app creates some redundancy, but we chose to accept this trade-off to make it
easier to view and modify everything relevant to the app. 

Meanwhile, if you find that modifications of lib/ modules are
necessary, please consider if your change would be generally beneficial for TEI Publisher and
create PR for the TEI Publisher if so. 

It is \TeiEmphasisI{considered safe} : 

\begin{enumerate}
\item {
to modify all HTML templates below templates/ as well as
index.html and search.html in the root of the
app 

}\item {
to change XQuery modules in modules, excluding those in
modules/lib

}\item {
to add images, fonts or change i18n translations below resources

}\item {
to add custom API functions (written in XQuery) to
custom-api.json and custom-api.xql

}\end{enumerate}

The following core XQuery modules in every app are safe to be modified (all are stored in
modules subcollection: 

\begin{description}
\item [
config.xqm
] 
The main configuration file for the app. It contains a number of parameters which
control important aspects.

\item [
custom-api.xql
] 
Custom API functions should be defined in this module - or a module imported by it.
Also, HTML templating modules should be imported into this module to be registered with
the TEI Publisher.

\item [
app.xql
] 
Add your own HTML templating functions in XQuery here if needed. With TEI Publisher
4.0 or later, there should be less of a need to extend this file as most of the
application logic is realized via web components.

\item [
pm-config.xql
] 
This file is usually generated by calling
modules/generate-pm-config.xql (see the corresponding section). It defines the functions to be
called for rendering TEI content via the processing model. It imports the modules
generated from your ODD and assigns them to variables as function pointers. This
approach is much more efficient than the dynamic lookups done by the main TEI Publisher
app. It has been production tested on large web sites. 

\item [
navigation-*.xql
] 
This group of modules contains functions relevant for the display and navigation of
documents corresponding to a given document type

\item [
query-*.xql
] 
Modules with functions powering the search features

\item [
view.xql
] 
The main module of the app. This module initializes eXist's templating system. The
only case when it should be modified is if you want to add further XQuery library
modules containing template functions.

\end{description}

\section*{Updating Applications}\markboth{Updating Applications}{Updating Applications}

\label{updating}
Custom applications are created from a specific version of TEI Publisher and may need to be updated over time to benefit from bug fixes and new features. If you followed the best practice recommendations, you can always update the core of TEI Publisher by replacing the modules/lib directory with the newer version. However, you may also need to adjust the configuration and code modules outside this directory to match the new release (details concerning a particular version are documented below). This obviously also applies to any custom code you have added or modified yourself. In general we would recommend the following procedure:

\begin{enumerate}
\item {Replace modules/lib

}\item {Check expath-pkg.xml for changed dependencies

}\item {
Have a look at the other XQuery files in modules: new releases
may introduce new files here, which should be copied. Also check if any of the other files
here were updated, e.g. facets.xql, nlp-config
etc. Make sure to keep your own changes.

}\item {Build your app and try to install it. This may result in errors to fix (e.g. variables/functions missing in modules/config.xqm.

}\item {Once the app starts and is functionally working, you can look into replacing other files, e.g.
the global CSS file in resources/css/theme.css or the javascript
utility files in resources/scripts.

}\end{enumerate}

For apps created with TEI Publisher 6 updating to 7 or 8 requires only small modifications.
Migrating from earlier versions, like 4 or 5, requires more effort, and is described in futher
sections.

\subsection*{Upgrading from TEI Publisher 9.0 to 9.1}

\label{upgrade-910}
This bug fix release is mainly relevant for Windows users running eXist-db directly (i.e. not via docker). The biggest change is the upgrade of
\TeiEmphasisII{tei-publisher-lib}: version 4.0.0 of the library introduced the possibility to directly reference variables and functions defined in TEI Publisher's main
configuration module (modules/config.xqm). While this is unproblematic in most environments, it causes a silent failure in windows
when compiling an ODD. The underlying reason is that config.xqm itself imports a large number of other modules, leading to
recursive imports, which eXist-db is currently unable to resolve properly on Windows. 

In general, importing all of config.xqm into the ODD generated code
is usually unnecessary as most of the settings are not needed. Version 4.0.1 of
\TeiEmphasisII{tei-publisher-lib} therefore no longer imports
config.xqm by default. Instead, you can configure the modules to be
made available via odd/configuration.xml (or
resources/odd/configuration.xml). By default, TEI Publisher 9.1
imports the dedicated modules/odd-global.xqm. 

To preserve backwards compatibility with apps generated by TEI Publisher 9.0,
tei-publisher-lib 4.0.1 will still import the entire config.xqm if no other module is
configured to be imported. However, to avoid unnecessary overhead, we strongly recommend to
switch to an explicit import as described below.

To update follow the generic instructions above and register the dedicated configuration
module:

\begin{enumerate}
\item {
If your ODD was using \$global anywhere, copy modules/odd-global.xqm from TEI Publisher 9.1 into the corresponding location of your app. Open the
module to check if the settings still match your custom application (e.g. if data-root is correct).

}\item {
Change your resources/odd/configuration.xml to include the module declaration:

\begin{lstlisting}[language=xml]
<modules>
<!-- Import global variables and functions from modules/odd-global.xqm -->
<module uri="http://e-editiones.org/tei-publisher/odd-global" prefix="global" at="odd-global.xqm"/>
...
</modules>
\end{lstlisting} 

}\end{enumerate}

\subsection*{Upgrading from TEI Publisher 8 to 9}

\label{upgrade-810}
To upgrade a custom application generated with TEI Publisher 8 to version 9, we recommend to have the source code of both, TEI Publisher 9 and the
custom application, in a local directory.

If you decide to work with the command line, as suggested here, clone TEI Publisher 9 into the directory one level above the one containing your own
application source code:

\begin{lstlisting}
git clone https://github.com/eeditiones/tei-publisher-app.git
cd tei-publisher-app
git checkout v9.0.0
\end{lstlisting} 
With both applications in place, work through the following steps:

\begin{enumerate}
\item {
Update server-side modules: those live in modules/lib. You can safely remove the entire folder and replace it with the
corresponding one from version 9 of TEI Publisher.

}\item {
Copy modules/facets.xql, modules/registers.xql, modules/iiif-config.xqm and
modules/annotation-config.xqm from TEI Publisher 9. If you modified any of these locally, you may need to compare.

}\item {
Update the webcomponents library to at least 2.15.3 (also see the \href{https://faq.teipublisher.com/webcomponents/version-upgrade/}{faq}). The version used is defined by a single variable in modules/config.xqm :

\begin{lstlisting}
declare variable $config:webcomponents := "2.15.3";
\end{lstlisting} 

}\item {
Change the dependency on \texttt{tei-publisher-lib} in expath-pkg.xml to 4:

\begin{lstlisting}[language=xml]
<dependency package="http://existsolutions.com/apps/tei-publisher-lib" semver="4" />
\end{lstlisting} 

}\item {
Edit resources/odd/configuration.xml and make sure you have an entry for the docx processing extension:

\begin{lstlisting}[language=xml]

<output mode="tei" odd="docx">
<module uri="http://www.tei-c.org/tei-simple/xquery/functions/docx" prefix="ext-docx"/>
</output>
\end{lstlisting} 

}\end{enumerate}

\subsubsection*{Upgrading the annotation editor}

\label{upgrade-annotation-editor}
If you are using the web-based annotation editor in your application, the following steps are required to update it to the redesigned version
shipping with Publisher 9:\begin{enumerate}
\item {
Copy templates/pages/annotate.html, the templates/pages/annotations and
resources/css/annotate.css subdirectory to the same location in your app

}\item {
Also copy the directory resources/scripts/annotations/ to the corresponding location

}\item {
If you did not change the annotation ODD to match your own requirements, you may also want to copy odd/annotations.odd
from TEI Publisher 9 into resources/odd/ of you app

}\item {
To update the HTML page for annotations, it is best to use the version from TEI Publisher 9 and copy over the sections you customized. While
the Publisher 9 version may look very different on first sight, the relevant, user-customizable parts have not changed much:\begin{itemize}
\item {
copy any customized toolbar buttons (class annotation-action) into the corresponding header element in the Publisher 9
version

}\item {
in the same way copy modified form controls (class annotation-form). In the new version those appear further down in the
HTML, but still look the same

}\item {
copy element <pb-authority-lookup>, including your custom authoritiy definitions

}\end{itemize}

}\end{enumerate}

\subsection*{Upgrading from TEI Publisher 7 to 8}

\label{upgrade7-8}
With TEI Publisher 8, we have factored out a number of functions away from the
\texttt{modules/lib} to give users more control over their searches and presentation of
the search results, which requires porting these functions into query modules of older apps.
Recent breaking change to the \texttt{tei-publisher-lib}, a consequence of offering the
Print CSS as a default print output also requires some manual updates.

The following changes have to be addressed during an update:

\begin{enumerate}
\item {
\texttt{tei-publisher-lib} was updated to version 3, including breaking changes

}\item {
version 1.x of the Open API library, roaster, requires namespace changes in module imports

}\item {
navigation and search have been refactored

}\end{enumerate}

To upgrade a custom application generated with TEI Publisher 7 to version 8, we recommend to have the source code of both, TEI Publisher 8 and the
custom application, in a local directory.

If you decide to work with the command line, as suggested here, clone TEI Publisher 8
into the directory one level above the one containing your own application source
code:

\begin{lstlisting}
git clone https://github.com/eeditiones/tei-publisher-app.git
cd tei-publisher-app
git checkout v8.0.0
\end{lstlisting} 
With both applications in place, work through the following steps:

\begin{enumerate}
\item {
Update the dependencies declared in the package descriptor file, expath-pkg.xml: 
this should include the following dependencies and versions:

\begin{lstlisting}[language=xml]
<dependency processor="http://exist-db.org" semver-min="5.3.0"/>
<dependency package="http://exist-db.org/html-templating" semver="1"/>
<dependency package="http://existsolutions.com/apps/tei-publisher-lib" semver="3"/>
<dependency package="http://e-editiones.org/roaster" semver="1"/>
\end{lstlisting} 
If present, remove the dependencies on \texttt{http://exist-db.org/apps/shared} and
\texttt{http://exist-db.org/open-api/router}.

}\item {
Update server-side modules: those live in modules/lib. You can
safely remove the entire folder and replace it with the corresponding one from the new
version.

}\item {
Update the webcomponents library to the latest 2.x.x release (also see the \href{https://faq.teipublisher.com/webcomponents/version-upgrade/}{faq}).
The version used is defined by a single variable in
modules/config.xqm :

\begin{lstlisting}
declare variable $config:webcomponents := "2.4.2";
\end{lstlisting} 
You may also want to switch to a different CDN. TEI Publisher by default used unpkg.com, which recently
became slightly unreliable. Change the corresponding variable to:

\begin{lstlisting}
declare variable $config:webcomponents-cdn := "https://cdn.jsdelivr.net/npm/@teipublisher/pb-components";
\end{lstlisting} 

}\item {
Just updating to the new \texttt{tei-publisher-lib} version requires two changes:

\begin{enumerate}
\item {
Update \texttt{resources/odd/configuration.xml}

If you registered any custom XQuery module in your
\texttt{resources/odd/configuration.xml} for the web output mode, make sure to
also enable this for the print output mode by copying the corresponding configuration
section as below 

If you never touched this file or don't know what it is for: skip this step. 

\begin{lstlisting}[language=xml]

<modules>
<output mode="web">
<module uri="http://karlbarth.ch/apps/kb/ext-html.xql" prefix="ext-html"
at="xmldb:exist:///db/apps/kb/modules/ext-html.xql"/>
</output>
<!-- we need to add this because print extends web -->
<output mode="print">
<module uri="http://karlbarth.ch/apps/kb/ext-html.xql" prefix="ext-html"
at="xmldb:exist:///db/apps/kb/modules/ext-html.xql"/>
</output>
</modules>

\end{lstlisting} 

}\item {
Change post-install.xql. In the function \texttt{local:generate-code}
you'll find a list of output modes. Add \texttt{fo} to this list:

\begin{lstlisting}

for $module in
if ($pi?output) then
tokenize($pi?output)
else
("web", "print", "latex", "epub", "fo")

\end{lstlisting} 

}\end{enumerate}

}\item {
Unless you applied changes to those files, copy all modules/query*.xql and
modules/navigation*.xql files. If you changed them, you'll need to diff and reapply
your modifications.

}\item {
Copy modules/nlp-config.xqm and modules/annotation-config.xqm.

}\item {
Check your modules/config.xqm for differences. In particular the variable
\$config:enable-proxy-caching needs to be copied.

}\item {
In modules/custom-api.xql (and any other module with API endpoints), replace the
following import namespaces:

\begin{itemize}
\item {
the \texttt{rutil} module import should be changed to:

\begin{lstlisting}
import module namespace rutil="http://e-editiones.org/roaster/util";
\end{lstlisting} 

}\item {
and the \texttt{errors} module import:

\begin{lstlisting}
import module namespace errors = "http://e-editiones.org/roaster/errors";
\end{lstlisting} 

}\end{itemize}

Also, if your module/custom-api.json file uses the \texttt{groups} property
anywhere, you need to change it to an array instead of a string, e.g.:

\begin{lstlisting}

"x-constraints": {
					"groups": ["tei"]
				},
\end{lstlisting} 

}\item {
Copy templates/documents.html into the corresponding folder of your custom app.

}\end{enumerate}

\subsubsection*{Other changes to pay attention to}

\label{other-changes7-8}
\begin{description}
\item [print/fo output modes] 
\texttt{tei-publisher-lib} 3.x.x reassigns the output mode \TeiEmphasisII{print} to
generate HTML output targetted at print. In older version \TeiEmphasisII{print} was defined as
an alias for \TeiEmphasisII{fo}. You may thus have to change your ODDs if you used the fo mode. A more 
elaborate explanation of the changes is presented in this
\href{https://www.e-editiones.org/posts/tei-publisher-lib-3/}{e-editiones article}.

\item [pb-facsimile/pb-facs-link] 
The behaviour of the \texttt{pb-facsimile} and \texttt{pb-facs-link} webcomponents has changed:
\texttt{pb-facs-link} must now emit to the event channel \texttt{pb-facsimile} is listening to.
Previously emitting to the default channel was enough. You should thus change all \texttt{pb-facs-link}
elements generated by your ODD to include an \texttt{@emit} attribute targetting the correct channel.

\item [HTML template links] 
If links, in particular in the menu, stop working and the indicated URL contains \texttt{\$\{...\}}, check the 
corresponding code in the HTML template. If
it has an attribute \texttt{data-template="lib:parse-params"}, change it to
\texttt{data-template="pages:parse-params"}. It should also be safe to run a search/replace
operation on all .html files in templates/.

\item [changed start page and templates] 
The start page of the TEI Publisher app has changed: it now integrates a full text search and
drops the `pb-browse-docs` component in favour of a plain `pb-load` and associated form controls. This
gives users more flexibility.

Old start pages using `pb-browse-docs` will still work as before, so you don't need to take any
action here. However, if you would like to upgrade, you'll need to manually compare and update
`templates/index.html`.

\end{description}

\subsection*{Upgrading from TEI Publisher 7 to 7.x}

\label{upgrade7}
Upgrading an app generated by TEI Publisher 7 to another minor release involves the
following general steps:

\begin{enumerate}
\item {
Update the webcomponents library (also see the \href{https://faq.teipublisher.com/webcomponents/version-upgrade/}{faq}).
The version used is defined by a single variable in
modules/config.xqm :

\begin{lstlisting}
declare variable $config:webcomponents := "1.24.12";
\end{lstlisting} 

}\item {
Update server-side modules: those live in modules/lib. You can
safely remove the entire folder and replace it with the corresponding one from the new
version.

}\end{enumerate}

\subsubsection*{Extra Steps for TEI Publisher 7.1}

\label{upgrade71}
The new annotation editor in TEI Publisher 7.1 requires a bunch of files to be copied.
If you do not intend to support web annotations in your app (we recommend having a
separate app for this), you only need step 1 and 2:

\begin{enumerate}
\item {
Copy modules/annotation-config.xqm into the corresponding
location in your app

}\item {
Copy templates/basic/controller.xql into the root of your
app. This contains an important security fix. If you modified your controller
yourself, just replace the last "else", which in the new version should start
with:\begin{lstlisting}
let $main :=
if (matches($exist:path, "^/+api/+(?:odd|lint)")) then 
"api-odd.xql" 
else if (matches($exist:path, "/+tex$") or matches($exist:path, "/+api/+apps/+generate$")) then
"api-dba.xql"
else 
"api.xql"
\end{lstlisting} 

}\item {
Copy odd/annotations.odd to
resources/odd in the generated app.

}\item {
Copy templates/pages/annotate.html and 
templates/pages/annotate.css to the corresponding folders.

}\item {
Also copy resources/scripts/annotations

}\end{enumerate}

\subsection*{Upgrading from TEI Publisher 6 to 7}

\label{update6-7}
With TEI Publisher 7, we have redesigned the server-side API. Combined with the
client-side reorganization brought by TEI Publisher 6, this will make future updates for
generated applications a lot easier. Client-side UI and server-side API are now cleanly
separated from any custom app elements.

To upgrade a custom application generated with TEI Publisher 6 to version 7, we
recommend to clone the source code of both, TEI Publisher 7 and the custom application, into
a local directory. The commands shown below were used on a Linux system for \href{https://github.com/eeditiones/dodis-wall/commit/491267575a97c101361e10de4001db2f97cc3d29}{updating the Dodis demo app}, but with appropriate adjustments to the syntax the
same actions could be performed on a different operating system. Alternatively the migration
can be executed using eXide's file manager. 

If you decide to work with the command line, as suggested here, clone TEI Publisher 7
into the directory one level above the one containing your own application source
code:

\begin{lstlisting}
git clone https://github.com/eeditiones/tei-publisher-app.git
cd tei-publisher-app
git checkout v7.0.0
\end{lstlisting} 
At this point we need to move to the directory where your own application source code is
stored:

\begin{lstlisting}
cd ../my-custom-app
\end{lstlisting} 

\subsubsection*{Copy files}

\label{updating-copy}
Now we need to remove the old modules/lib directory and replace
it entirely with the new one from the TEI Publisher 7. We'll also copy a bunch of files
from the templates subdirectory of TEI Publisher: 

\begin{lstlisting}

rm -rf modules/lib
cp -r ../tei-publisher-app/modules/lib/ modules/
cp ../tei-publisher-app/templates/basic/pre-install.xql .
cp ../tei-publisher-app/templates/basic/post-install.xql .
cp ../tei-publisher-app/templates/basic/controller.xql .
cp ../tei-publisher-app/resources/css/theme.css resources/css
cp ../tei-publisher-app/templates/basic/modules/custom-api.* modules/
cp ../tei-publisher-app/templates/basic/modules/facets.xql modules/
cp ../tei-publisher-app/templates/api.html templates/
\end{lstlisting} 
Ideally, these files should not have been modified by you, if you followed our
earlier best practice recommendations.
Otherwise you may need to reapply your changes. 

Next, copy the navigation* and query*
modules. These are intended to be customized, so you may have changed them in your custom
app. Compare the versions and make sure you reapply your modifications, if any. 

\begin{lstlisting}
cp ../tei-publisher-app/modules/navigation* modules/
cp ../tei-publisher-app/modules/query*.xql modules/
\end{lstlisting} 
\begin{mdframed}[frametitle={}]
Note that the naming of the query-*.xql has changed to be
constistent with the navigation-*.xql files. 

\end{mdframed}
Same considerations apply to the HTML templates for menus and the toolbar.
Nevertheless, changes in these areas were quite minor, so you may alternatively postpone
this step untill you encounter concrete issues in your application:

\begin{lstlisting}
cp ../tei-publisher-app/templates/menu.* templates/
cp ../tei-publisher-app/templates/toolbar.html templates/
cp ../tei-publisher-app/templates/drawer.html templates/
\end{lstlisting} 

\subsubsection*{Edit HTML templates}

\label{updating-templates}
\begin{mdframed}[frametitle={\paragraph*{Important}

}]
TEI Publisher 7 expects all HTML files to reside in the
templates subfolder. Previous versions used a mix of locations
with some HTML files in the root of the app. You should thus copy your
index.html,  search.html,
error-page.html and any other custom HTML files into
templates first. 

\end{mdframed}
Also, because TEI Publisher 7 has a well-defined API to handle the communication
between user interface components and server-side functionality, we need to change some of
the URLs in the HTML templates we're using. As a rule of thumb, all URLs previously
calling XQuery modules directly, should now start with \texttt{api/} followed by the
correct API path. The main HTML template to be changed is index.html
. Please search and replace the properties for the following webcomponents: 

\begin{lstlisting}[language=xml]
<pb-download url="modules/lib/app-download.xql">
\end{lstlisting} 
should be changed into

\begin{lstlisting}[language=xml]
<pb-download url="api/apps/download">
\end{lstlisting} 
and

\begin{lstlisting}[language=xml]
<pb-custom-form id="facets" url="modules/facets.xql" event="pb-results-received" subscribe="docs" emit="docs"/>
<pb-browse-docs id="document-list" url="collection/" ...>
\end{lstlisting} 
should be changed into

\begin{lstlisting}[language=xml]
<pb-custom-form id="facets" url="api/search/facets" event="pb-results-received" subscribe="docs" emit="docs"></pb-custom-form>
<pb-browse-docs id="document-list" url="api/collection/" ...>
\end{lstlisting} 
The last change should also be applied to search.html and you
should change the <pb-load> loading the search results to read: 

\begin{lstlisting}[language=xml]
<pb-load id="results" url="api/search" emit="results"></pb-load>
\end{lstlisting} 
Also check templates/pages/view.html and any other page template
your app uses. Search for calls to .xql or
modules/ and replace them with appropriate API paths. If you were
making direct calls to custom modules, e.g. from \texttt{pb-load} component, these
need to be added as custom API endpoints. 

\subsubsection*{Update config.xqm}

\label{updating-config}
Finally, a few settings need to be added to the main configuration module, 
modules/config.xqm : 

\begin{enumerate}
\item {
Change \$config:webcomponents to at least version \texttt{
1.13.0}. 

}\item {
Check for missing variables or functions and copy these from 
tei-publisher-app/templates/basic/modules/config.xqm, in particular: 

\begin{itemize}
\item {
\$config:odd-available

}\item {
\$config:odd-internal

}\item {
config:collection-config()

}\item {
config:default-config()

}\item {
config:document-type()

}\item {
config:get-document()

}\end{itemize}

}\end{enumerate}

\subsubsection*{Check for other customizations}

\label{customizations6-7}
In most cases you will now be able to rebuild your custom app, redeploy it to eXist
and test. If you encounter any error messages, they are most likely due to additional
modifications you applied to your custom app. These are usually located in two main
areas:

\begin{description}
\item [Custom HTML templating functions] 
Earlier versions of TEI Publisher relied heavily on eXist's HTML templating
framework and custom apps would add their own templating functions into 
modules/app.xql (or additional modules). This approach is still
perfectly valid. 

Everything will work as expected if you've just extended 
modules/app.xql. However, if you have added other modules containing
templating functions, now you need to import these explicitly into 
modules/custom-api.xql. 

\item [Custom XQuery main modules] 
If your custom app makes direct calls to XQuery main modules (e.g. via the
\texttt{ pb-load} component), these have to be rewritten. TEI Publisher 7
expects all API calls to go through the Open API router - direct calls to XQuery
modules are no longer supported. Therefore you need to transform your code into
functions which can be called via the Open API, e.g. by adding them to
modules/custom-api.xql or importing them there. 

\end{description}

\subsubsection*{Remove superfluous code}

\label{customizations6-7-cleanup}
Now you can remove files which are no longer used:

\begin{lstlisting}

rm templates/toc.html
rm templates/search-results.html
rm modules/view.xql
\end{lstlisting} 

\subsubsection*{Change API endpoints}

\label{customizations6-7-endpoints}
Finally, to be able to view and test the API of your custom app, you should change
the endpoints in the Open API specification files. In both,
\texttt{modules/lib/api.json} and \texttt{modules/custom-api.json}, change the
url property in the following section: 

\begin{lstlisting}

"servers": [
{
"description": "Endpoint for testing on localhost",
"url": "http://localhost:8080/exist/apps/tei-publisher"
}
],
\end{lstlisting} 
Change the final part of the URL to match the name of your app instead of
"tei-publisher". If you are on a remote server, adjust the whole url accordingly.

\subsection*{Migrating from TEI Publisher 4, 5 or earlier}

\label{update5-7}
If you are migrating to version 7 from TEI Publisher 5, 4 or earlier, you also need to
pay attention to the user interface redesign introduced by TEI Publisher 6. This makes
things more difficult and there are two possible approaches for updating:

\begin{itemize}
\item {
generate a new application with TEI Publisher 7 and merge your changes in into the
newly generated app. This is the recommended method. If your customizations were limited
to e.g. ODD files, CSS styles, templates, index configurations or adding your own code
in modules/, it should all go very smoothly. 

}\item {
update your generated app by modifying the HTML templates you use and copying files
from TEI Publisher.

}\end{itemize}

The first option is strongly recommended and much easier in general. The second option
is only for experienced users who have to update apps containing a lot of customized
code.

\subsubsection*{Update by Generating a New Application}

\label{update5-7-newapp}
\begin{enumerate}
\item {
Upload your customized ODD to the TEI Publisher 7

}\item {
If you created a custom HTML template for your document view, upload it to the
templates/pages collection of the TEI Publisher. You can use
eXide's file manager to do so. 

}\item {
Generate a new application using your custom ODD. Make sure to choose a different
URL and short name to not confuse the old and new app.

}\item {
Adjust modules/config.xqm variables, if necessary. 

}\item {
Selectively upload all other files you changed or resources you added to the
generated app (data, CSS). In case of custom page templates and XQuery modules follow
recommendations for updating from Publisher 6.

}\end{enumerate}

\subsubsection*{Update by copying}

\label{update5-7-copy}
\begin{mdframed}[frametitle={}]
This approach is for experienced users only and not recommended. We mainly keep it
here for reference. This guide has been created for updating to TEI Publisher 6, so you
will also need to follow the instructions for migrating from 6
to 7 and apply the steps not described below. 

\end{mdframed}
The following steps assume that you either

\begin{itemize}
\item {
have a copy of your app's code on the filesystem and either a clone of TEI
Publisher 6 or an app skeleton generated by TEI Publisher 6 (preferred) next to
it

}\item {
or have your app and TEI Publisher installed in your database. In this case use
eXide's file manager to copy files

}\end{itemize}

In the following, the TEI Publisher 6 app you are copying from will be identified as
\$source. 

\begin{enumerate}
\item {
Edit modules/config.xqm and add two variables at the top:
\texttt{ \$config:origin-whitelist} and \texttt{\$config:webcomponents}. 

\$config:webcomponents should point to the latest version of
pb-components. 

\begin{lstlisting}

(:~
: A list of regular expressions to check which external hosts are
: allowed to access this TEI Publisher instance. The check is done
: against the Origin header sent by the browser.
:)
declare variable $config:origin-whitelist := (
"(?:https?://localhost:.*|https?://127.0.0.1:.*)"
);

(:~~
: The version of the pb-components webcomponents library to be used by this app.
: Should either point to a version published on npm,
: or be set to 'local'. In the latter case, webcomponents
: are assumed to be self-hosted in the app (which means you
: have to npm install it yourself using the existing package.json).
: If a version is given, the components will be loaded from a public CDN.
: This is recommended unless you develop your own components.
:)
declare variable $config:webcomponents := "0.9.11";
\end{lstlisting} 
Other variables in conf.xml which may need to be updated
are: 

\begin{itemize}
\item {
\$config:data-default

}\item {
\$config:data-exclude

}\item {
\$config:context-path

}\end{itemize}

}\item {
Copy all XQuery files from \$source/modules/lib into the
modules/lib of your application. 

}\item {
Copy \$source/resources/css/theme.css into the same location
in your application. 

}\item {
In all HTML files \TeiEmphasisII{you changed for your app}, check
<head> and remove any <script> element or <link> doing an
import like: 

\begin{lstlisting}[language=html]
<link rel="import" href="components/dependencies-dev.html"/>
\end{lstlisting} 
Instead add the following line to the head:

\begin{lstlisting}[language=html]
<script type="module" src="pb-components-bundle.js" data-template="pages:load-components"></script>
\end{lstlisting} 
Also add a link to theme.css : 

\begin{lstlisting}[language=html]
<link rel="stylesheet" href="resources/css/theme.css"/>
\end{lstlisting} 

}\item {
Copy \$source/resources/css/theme.css

}\item {
Copy \$source/resources/i18n. The existing
*.xml in your directory can be deleted - unless you added your
own translated keys, in which case you would need to move them into the corresponding
json format. 

}\item {
HTML files you did not change may just be overwritten by copying the
corresponding versions from \texttt{\$source}. In particular this includes files in
the \$source/templates/basic/templates subdirectory. 

}\item {
Copy \$source/templates/basic/controller.xql into the root of
your application - unless you made changes to this file yourself, in which case you
would need to merge it. 

}\item {
Check the files in modules within your app: if you have not changed any of them,
just copy the corresponding files from tei-publisher-app/modules
. See if you need to merge the modified ones. 

}\item {
i18n translations are now applied client-side rather than server-side. This means
you should drop all references to \texttt{data-template="i18n:translate"} and the
i18n namespace from your HTML. Also remove the i18n module import from your 
modules/view.xql or overwrite the file if you have not modified it.

}\end{enumerate}

You may consult the diff of an actual update from Publisher 5 to 6 in the dodis-wall
repository on github: \href{https://github.com/eeditiones/dodis-wall/commit/9c3757d909932db458d2a777b7a952a8ee4dcc9e}{update to publisher 6: update templates, configuration and
styling}

\section*{Data}\markboth{Data}{Data}

\label{data-organization}
TEI Publisher ships its data files within the same application package. Nevertheless,
separating your data from application code has many benefits, particularly for actively
developed applications and data sets. This way changes to your code can be deployed without
redeploying and reindexing your data and vice versa. It is also easier to maintain separate
repositories (e.g. in Git) and differentiate privileges for editorial and developer
teams.

While we would generally recommend separating data and code, some projects may still
prefer to keep their data and application integrated in a single \TeiEmphasisII{xar}
package for the sake of marginally easier distribution. 

Internal structure of the data collection can be arbitrary, though there are some
considerations regarding index configuration to take into account.

\subsection*{Data collection}

\label{data-collection}
Two variables in config.xqm are used to configure location of the
data collection. \texttt{\$config:data-root} specifies where in the collection hierarchy
the data is stored. Only the top level collection needs to be specified. 

\begin{lstlisting}

(:~
: The root of the collection hierarchy containing data.
:)
declare variable $config:data-root := $config:app-root || "/data";

\end{lstlisting} 
Switching to a separate data package is as simple as changing this variable, e.g.
assuming that we store our data in \texttt{/db/apps/lgpn-ling-data/data}, the \texttt{
data-root} should be defined as: 

\begin{lstlisting}

declare variable $config:data-root := '/db/apps/lgpn-ling-data/data';

\end{lstlisting} 
In the variable \$config:data-exclude you may specifiy a sequence
of root elements which should be excluded from the list of document shown in the browsing
view, e.g. secondary data files like a taxonomy or entity lists. 

You may find it helpful to create and build the data package starting from the template
hosted in the \href{https://github.com/eeditiones/tei-publisher-data-template}{e-editiones repository}. README document provided there explains
shortly roles of all the files and how to adjust them to your needs. 

\begin{mdframed}[frametitle={}]
It is critical to store index configuration file,
collection.xconf in the correct location. Refer to \href{https://exist-db.org/exist/apps/doc/indexing.xml}{eXist-db
documentation} for details but it is common practice to store a collection
configuration in the data package and rely on mechanisms of pre-install script (
pre-install.xql) to copy the file to its required position in
/db/system/config. 

Similar consideration applies if fulltext index makes use of any external function
module, which in TEI Publisher and generated apps is commonly the case for facet and field
definitions. This module needs to be stored before the index is to be applied and usually
it's best to store it in the same location as collection.xconf.

\end{mdframed}

\subsection*{Subcollections}

\label{subcollections}
Many editions will simply present a number of documents, e.g. a collection of letters
like \href{https://tei-publisher.org/exist/apps/vangogh/index.html}{Van Gogh} or plays like \href{https://tei-publisher.org/exist/apps/shakespeare-pm/index.html}{Shakespeare} demo. Structure of the data is therefore very simple, all the files
are stored on the same level in the \texttt{data-root} collection. 

Other publications, particularly those including heterogeneous material may require a
more complex organization. TEI Publisher itself is a good example - its \texttt{data}
collection is further divided into three subcollections: doc (for
documentation), test (for examples) and playground
(for user-supplied material). 

\begin{figure}[h]
\caption{Structure of TEI Publisher's data collection}

\includegraphics[max size={\textwidth}{\textheight}]{data-collection.png}

\end{figure}

You will note that it also contains other resources: image files and even an HTML file.
Specify the \texttt{\$config:data-default} variable in
modules/config.xqm to set which collection should be used as a point
of entry to your data. Whenever  collection.html is present in that
location, it will be used as a custom landing page displayed instead of a simple document
listing. In case of the TEI Publisher it would be the Demo Collection, Playground and
Documentation 

\begin{lstlisting}

(:~
: The root of the collection hierarchy whose files should be displayed
: on the entry page. Can be different from $config:data-root.
:)
declare variable $config:data-default := $config:data-root;

\end{lstlisting} 
This approach can be extended further, say if you wanted to add a
prints and manuscripts subcollection to the
playground and present them in a custom landing page. Just add the
data and a corresponding  collection.html into the
playground. You can shape the custom landing page however you like,
using the full power of HTML and eXist templating. 

\begin{figure}[h]
\caption{Subcollections}

\includegraphics[max size={\textwidth}{\textheight}]{data-subcollections.png}

\end{figure}

\begin{figure}[h]
\caption{Fragment of the subcollections landing page}

\includegraphics[max size={\textwidth}{\textheight}]{data-subcollection-landing.png}

\end{figure}

The landing page like this could be created with this HTML template stored in
data/playground/collection.html. 

\begin{lstlisting}[language=html]

<div class="collection" data-template="browse:clear-facets">
<h3>Custom landing page demonstrating sub-subcollections.</h3>
<ul class="documents">
<li class="document">
<div class="thumbnail"><img src="demo.png" width="128"/></div>
<div class="document-info">
<h3><a href="#" data-collection="playground/prints">Prints</a></h3>
<p>This one is for prints.</p>
</div>
</li>
<li class="document">
<div class="thumbnail"><img src="demo.png" width="128"/></div>
<div class="document-info">
<h3><a href="#" data-collection="playground/manuscripts">Manuscripts</a></h3>
<p>This one is for manuscripts.</p>
</div>
</li>
</ul>
</div>

\end{lstlisting} 

\subsection*{Processing instructions}

\label{pi-config}
The default view for a specific document can be configured via a processing
instruction. Before displaying a document, TEI publisher will check if a processing
instruction exists at the start of the document, telling it which ODD and view template to
use (along with other configuration parameters). For example, the following processing
instruction associates the document with the view template
translation.html, the ODD dantiscus.odd, and
switches to a page-by-page display (along TEI page break boundaries): 

\begin{lstlisting}[language=xml]
<?teipublisher template="translation.html" odd="dantiscus.odd" view="page"?>
\end{lstlisting} 
When viewing the document by structural divisions, two additional settings control the
amount of content displayed at a time:

\begin{lstlisting}[language=xml]
<?teipublisher depth="2" fill="6" odd="dta.odd"?>
\end{lstlisting} 
\begin{description}
\item [odd] 
The ODD file to use for rendering the document.

\item [template] 
The HTML view template to use. Default is \texttt{view.html} as configured in
modules/config.xqm. 

\item [view] 
Default view to show when browsing the document. Supported values are 
div, page or single : 

\begin{enumerate}
\item {

div : displays one structural division (TEI div, DocBook
section …) at a time 

}\item {

page : displays the document page by page. This requires
page break indicators to be present (<pb> in TEI, not supported for
DocBook). 

}\item {

single : the entire document (or a selected fragment of it)
is displayed at once 

}\end{enumerate}

\item [depth] 
When viewing entire divisions, the software tries to determine if it should show
child divisions in separate pages or include them with the current div.
<depth> indicates the nesting level up to which divisions should be shown
separately. So setting it to "2" will result in divisions on level 3 or greater to be
shown together with their enclosing div. 

\item [fill] 
If child divisions appear on separate pages, it may happen that the enclosing div
contains just a heading or a single line of text. In this case, the algorithm will try
to fill the page by showing the first child division as well. The <fill>
paramter defines the number of elements which should at least be present on a page. If
not, the software tries to fill it up. 

\item [media] 
A space separated list of output media types supported for this document. TEI Publisher 8 uses this
information to limit the
download options shown to the user. The output type
\texttt{web} is always assumed to work and does not need to be specified. Other supported output media types
are:

\begin{itemize}
\item {
epub

}\item {
print

}\item {
fo

}\item {
latex

}\end{itemize}

For example, this documentation uses the following settings in its processing instruction:

\begin{lstlisting}[language=xml]
media="latex print fo epub"
\end{lstlisting} 

\end{description}

\section*{Facet Search Configuration}\markboth{Facet Search Configuration}{Facet Search Configuration}

\label{facets}
Facets allow users to quickly navigate through a set of documents or query results by
selecting from predefined categories or properties. This way, users can "drill down" into the
set, reducing the number of displayed items with every step. For demonstration purposes, TEI
Publisher configures two facets by default: "Genre" and "Language". You can see those to the
left of the document list on the start page, or below the search box on the search result
page.

\begin{figure}[h]
\caption{Facets on the start page}

\includegraphics[max size={\textwidth}{\textheight}]{facets.png}

\end{figure}

From a user perspective, the main concept behind facets is the \TeiEmphasisII{drill
down} : initially the user sees all facet values associated with the set of
documents or search results displayed. The number behind each value denotes the number of
items in the set having the particular facet set. As the user selects one facet, the set
necessarily becomes smaller, so non-matching facet values will disappear and the numbers
adjust accordingly. 

Facets are a new feature in eXist 5.0. They are super fast because eXist will create them
when indexing the document. No extra computation is needed when the user clicks on a facet to
drill down into a displayed set: all information is already available in the index. To see a
more complex example of facets in action, visit our \href{https://tei-publisher.org/exist/apps/vangogh/index.html}{Van Gogh} demo. 

If you would like to configure other or additional facets, you need to edit three
files:

\begin{description}
\item [
collection.xconf
] 
The collection.xconf tells eXist how to index the collection.
The default configuration in TEI Publisher creates two Lucene full-text indexes for TEI
on <tei:text> and <tei:div>. Each of those may have facets attached.
Every facet must have a dimension and an
expression attribute. The expression is an arbitrary
XPath/XQuery string. For every element being indexed, the expression is evaluated once
and the result defines the string values which will be associated with the specified
facet dimension. 

For a description of how full-text indexes and facets are defined in the 
collection.xconf, please refer to the \href{http://exist-db.org/exist/apps/doc/lucene}{eXist documentation}.

\item [
index.xql
] 
If you open the default collection.xconf, you'll see that most
facet expressions call a function nav:get-metadata. This function
is declared in index.xql. By externalizing most of the code into a
separate function, we can keep the index configuration clean and short. 

The default index.xql already does some advanced
preprocessing, in particular for the "genre" facet: each of the sample documents
references a central taxonomy (contained in data/taxonomy.xml). The
references are resolved at indexing time by following the <catRef> element's
@target attribute. Note that we create a hierarchical facet,
because e.g. "Philosophy" is a sub-category of "Prose". The code in function 
idx:get-genre will automatically include the super-category. 

\item [
config.xqm
] 
While the other two files cover the server-side creation of facets, we also need a
place where we define how facets should be displayed in the user interface. The main
configuration module: config.xqm declares a variable 
\$config:facets. It should contain an array of maps, where each map defines
the settings for one dimension, e.g.: 

\begin{lstlisting}

(:
: Display configuration for facets to be shown in the sidebar. The facets themselves
: are configured in the index configuration, collection.xconf.
:)
declare variable $config:facets := [
map {
"dimension": "genre",
"heading": "Genre",
"max": 5,
"hierarchical": true()
},
map {
"dimension": "language",
"heading": "Language",
"max": 5,
"hierarchical": false(),
"output": function($label) {
switch($label)
case "de" return "German"
case "es" return "Spanish"
case "la" return "Latin"
case "fr" return "French"
case "en" return "English"
default return $label
}
},
map {
"dimension": "feature",
"heading": "facets.feature",
"source": "api/search/facets/feature",
"max": 5,
"hierarchical": false()
},
];

\end{lstlisting} 
The map properties are as follows:

\begin{description}
\item [dimension] 
The name of the dimension. Should correspond to the value of the 
@dimension attribute used in collection.xconf

\item [heading] 
The heading to display above the facet values

\item [max] 
Maximum number of facet values to be displayed initially. More can be shown
if the user clicks on the \TeiGuilabel{Show All} checkbox. Pass an empty
sequence, i.e. (), to not limit the number and hide the checkbox. 

\item [hierarchical] 
Defines if the facet is hierarchical, which means that only the top-level
facet values in the hierarchy will be shown initially. If the user selects one
top-level value, the interface will expand and show the sub-categories. For this
to work the facet must be configured as "hierarchical" in 
collection.xconf

\item [output] 
A function which can be used to process the facet value before display. The
facet label will be replaced by whatever the function returns.

The function may accept a single (taking the current facet value), or two parameters
(current facet value and selected UI language).

\item [source] 
In addition to checkboxes, a combo box can be displayed into which users can type to search for
and select a facet. This is in particular useful for potentially long facet lists. The \texttt{source}
property should point to an API endpoint from which the current list of matching facets is being
retrieved. TEI Publisher provides a default implementation of this API function in 
modules/lib/api/search.xql, \texttt{sapi:list-facets}.

If an \texttt{output} function is provided, facet labels are passed to it before display.
Note that the combo box won't work with hierarchical facets.

\end{description}

\end{description}

\section*{Embedding TEI Publisher in other systems}\markboth{Embedding TEI Publisher in other systems}{Embedding TEI Publisher in other systems}

\label{embedding}
Since version 6.0, all \texttt{pb-components} can be used
\TeiEmphasisII{outside} TEI Publisher itself. The components can be embedded into any
environment, e.g. a CMS or blog software (like WordPress or Drupal) or integrated into any
modern front-end framework (like vue, react or angular). All that is needed is a TEI Publisher
instance available on the web which stores the source TEI and provides a communication
endpoint for the components to talk to. 

\subsection*{Live Examples}

\label{embedding-examples}
The embedded example below demonstrates such a use case: it provides a sandbox running
on \href{https://codepen.io}{codepen.io} but communicates
with the TEI Publisher instance on \href{https://tei-publisher.org}{teipublisher.com} which stores the documents.
The magic happens in the \texttt{endpoint} attribute passed to <pb-page>, which
tells the components where to talk to: 

\begin{lstlisting}

\end{lstlisting} 
You can actually edit the code above: for example, try to change the path for the first
document to test/F-rom.xml and the odd to \texttt{shakespeare}. See
how the live view changes? 

And if you would like to read \TeiEmphasisII{Romeo and Juliet} in two-column mode,
just add \texttt{column-separator=".tei-cb"} to the main <pb-view>. 

\subsection*{Retrieving the whole document as a simple HTML}

\label{embedding-whole-doc}

Embedding results of applying Processing Model transformation on a document is even
simpler. Behind the scenes, TEI Publisher has a separate library part, which is essentially
an implementation of the TEI processing model. This library can be used independently to
retrieve the entire content of a TEI document as HTML, transformed through an ODD with
processing instructions.

All you need is a small XQuery which calls the library modules, setting the correct
source document and ODD. Fortunately, TEI Publisher already contains a boilerplate XQuery
script for this job, which you can call as follows in your browser:

\href{https://tei-publisher.org/exist/apps/tei-publisher/api/document/test%2FF-rom.xml/html?odd=shakespeare.odd}{
https://tei-publisher.org/exist/apps/tei-publisher/api/document/test\%2FF-rom.xml/html?odd=shakespeare.odd}

This will retrieve the content of Shakespeare's \TeiEmphasisII{Romeo and Juliet}
as an HTML page, transformed through the odd shakespeare.odd. For
embedding an entire document in an iframe or similar, this should already be enough. Please
note that \TeiEmphasisI{/} character in the path to the document
test/F-rom.xml had to be URL encoded as \%2F
. 

\subsection*{Embedding webcomponents for navigation}

\label{embedding-webcomponents}
For longer documents, embedding the entire content in a page may not be too
user-friendly. A better way is to use the library of webcomponents provided by TEI
Publisher. This way, we can show the content page by page or division by division, allowing
the reader to navigate between sections.

\begin{lstlisting}

\end{lstlisting} 
Because webcomponents are part of the HTML5 standard and supported natively by most
modern browsers, we can easily import the component library which is at the core of the TEI
Publisher app and reuse the components it provides in other contexts. They should work in
any HTML5 page, no matter if it was written by hand, is generated by PHP, Python or a
CMS.

For a start, the page should import two scripts in its header:

\begin{lstlisting}[language=html]
<script src="https://cdn.jsdelivr.net/npm/web-components-loader/lib/index.min.js"></script>
<script type="module" src="https://cdn.jsdelivr.net/npm/@teipublisher/pb-components/dist/pb-components-bundle.min.js"></script>
\end{lstlisting} 
This imports necessary \texttt{pb-components} libraries from
\texttt{jsdelivr.net} CDN which is considered the best practice for web sites. 

The second <script> tag imports all the components provided by TEI Publisher.
Note that here \texttt{pb-components@latest} points to the latest available bundle, but
you could specify a concrete version number to make sure your website uses a fixed release. 

Now let's actually use the components to display Shakespeare's \TeiEmphasisII{Romeo and
Juliet} : in the HTML <body>, include the following snippet: 

\begin{lstlisting}[language=html]
<pb-page endpoint="https://tei-publisher.org/exist/apps/tei-publisher">
<pb-document id="document1" path="test/F-rom.xml" odd="shakespeare"></pb-document>
<!-- Navigate to previous page -->
<pb-navigation direction="backward" unit="page" keyboard="left">
<paper-button>
<iron-icon icon="icons:chevron-left"></iron-icon>
</paper-button>
</pb-navigation>
<pb-view id="view1" src="document1" view="page"></pb-view>
<!-- Navigate to next page -->
<pb-navigation direction="forward" unit="page" keyboard="right">
<paper-button>
<iron-icon icon="icons:chevron-right"></iron-icon>
</paper-button>
</pb-navigation>
</pb-page>
\end{lstlisting} 
In the <pb-page>
\texttt{endpoint} attribute we need to provide a critical piece of information: the URL
of the TEI Publisher instance for all the components to communicate with. If you have set up
your own instance of eXist-db and TEI Publisher, you should change the URL \TeiEmphasisII{to
point to your instance}. This is important because the components will expect
the documents you want to display to be stored in the same instance. 

<pb-document> defines the document to be displayed. The path is relative to the
data root of the TEI Publisher instance. It also specifies the ODD to be used for the
transformation. 

<pb-view> is the main component for displaying the transformed content. It
references the <pb-document> to use as source in its src
attribute. The Shakespeare does tag page breaks, so we switch to page-by-page view via the
view attribute to show the user only one page at a time. The default
would be to use a division-by-division view (\texttt{view="div"}), but you could also
request the entire content at once using \texttt{view="single"}. 

<pb-navigation> adds forward/backward navigation buttons to the page, allowing the
user to switch to the next/previous page of the document. You can use various types of
buttons, but in this case we're choosing a <paper-button> element with a chevron
< iron-icon> (both <paper-button> and <iron-icon> are part of
the standard \href{https://www.webcomponents.org/author/PolymerElements}{Polymer elements
library}). 

Another example of embedding TEI Publisher web components into a static website can be
found on our \href{https://teipublisher.onrender.com/}{demo blog}. It was
created with \href{https://gohugo.io}{Hugo}, a very popular website
generator which offers hundreds of ready-made themes to choose from. Here content is written
in markdown, but its not a problem to embed TEI content served by TEI Publisher. 

\section*{Creating Custom Web Components}\markboth{Creating Custom Web Components}{Creating Custom Web Components}

\label{custom-components}
In some cases an app may need to add its own web components to the collection provided by
TEI Publisher. Please consider following \TeiEmphasisI{open-source-first
approach}, as we do, and contributing your component back to the community, for
others to use. 

For that reason, we recommend here a setup which leads to relatively smooth integration
with \texttt{pb-components} in the future. 

Start with forking and downloading the \texttt{pb-extension-template} package from
its \href{http://github.com/eeditiones/pb-extension-template}{GitHub repository}. 

\begin{figure}[h]
\caption{Visual Studio Code overview of pb-extension-template}

\includegraphics[max size={\textwidth}{\textheight}]{component-extension.png}

\end{figure}

You will find it already includes several configuration files to get you started on the
development.

\begin{itemize}
\item {

package.json file which includes definition and specifications for
common task, like generating documentation or running a web server for local development

}\item {

src directory to put your custom web component code. It already
includes pb-clipboard.js file as an example of a simple component

}\item {

index.html file which illustrates the simplest scaffolding for using
your new components 

}\item {

demo directory to place your demo files for testing and documentation
purposes. It already contains demo.js configuration file and
pb-clipboard.html demo for <pb-clipboard>. 

}\item {

api.html file serving as a documentation starting point for your
package 

}\item {

rollup.config.js provides building specification to create a bundle
that can be included in any web page. 

}\end{itemize}

To get you started, run \texttt{npm install}. This will install required
dependencies: above all \texttt{pb-components} but also \texttt{es-dev-server} and
\texttt{ web-component-analyzer} packages which are needed for local development and
documentation. 

\begin{figure}[h]
\caption{Visual Studio Code snippet}

\includegraphics[max size={\textwidth}{\textheight}]{litelem-vscode-snippet.png}

\end{figure}

If you are using Visual Studio code .vscode/component.code-snippets
will provide you with code templates. If you create a new file in src,
e.g. pb-foo.js and start typing \TeiEmphasisII{litelement} you will
be offered a LitElement template. Otherwise you can copy the template manually or copy
existing <pb-clipboard> element and tweak it. 

\begin{figure}[h]
\caption{LitElement template}

\includegraphics[max size={\textwidth}{\textheight}]{litelem-template.png}

\end{figure}

\subsection*{pb-clipboard example}

\label{custom-components-clipboard}
We will discuss the details of the <pb-clipboard> element to illustrate some
basic concepts. You will find exact code of this example in \texttt{
pb-extension-template/src/pb-clipboard.js}. Each custom component has a defined API:
an interface it presents to the outside world. It includes properties, methods (also called
functions) and events but it bundles HTML markup along with local CSS and JavaScript into a
single file. 

Our example is a custom element designed to provide simple
\TeiEmphasisII{copy-to-clipboard} functionality, helpful e.g. when providing
ready-made citation on a page. It consists of three parts: a label, the content to be copied
and a button to copy. 

Thus, render function which actually displays this custom component could look like
this:

\begin{lstlisting}

render() {
return html`
<h3>${translate(this.label)}</h3>
<div>
<slot></slot>
<paper-icon-button icon="icons:content-copy" @click="${this._copy}"
title="${translate('clipboard.copy')}"></paper-icon-button>
</div>
`;
}

\end{lstlisting} 
You will note that the render function uses not only regular HTML elements like
<h3> or <div> but also components from the \texttt{paper-} package.
To be able to use them, we need to explicitly import them. Same is true for
\texttt{LitElement} class itself and important interface from the
\texttt{pb-components} package: \texttt{pbMixin}. 

All user interface components may need to be localized. For that reason we also import
\texttt{ translate} method from TEI Publisher's \texttt{i18n} module. 

\texttt{LitElement} and \texttt{pbMixin} must be imported for all custom components
extending \texttt{pb-components}. Code listing below demonstrates how to correctly
import all classes and custom elements required as well as how to create a class signature
that extends \texttt{pbMixin}. 

\begin{lstlisting}

import { LitElement, html, css } from 'lit-element';
import { pbMixin } from '@teipublisher/pb-components/src/pb-mixin';
import { translate } from "@teipublisher/pb-components/src/pb-i18n";
import '@polymer/paper-icon-button';
import '@polymer/iron-icons';

/**
* A component with a button which copies the contained content to the clipboard.
* Use for the typical 'quote this content as' hints on a webpage.
* 
* @slot content - contains the actual content to copy to the clipboard
*/
export class PbClipboard extends pbMixin(LitElement) {

\end{lstlisting} 

Imports and render function sorted, there are two other static functions we need to
take care of: properties and styles. \texttt{
pb-clipboard} has just a single property: the label to display above the copy text.
Nevertheless it needs to explicitly declare properties inherited from pbMixin which is done
via \texttt{...super.properties} notation. 

\begin{lstlisting}

static get properties() {
return {
/**
* Label to display above the text to be copied
*/
label: {
type: String
},
...super.properties
};
}

\end{lstlisting} 

You probably noticed that the button we added in the render
function specifies what to do upon click event via \texttt{click} attribute: \texttt{
@click="\$\{this.\textunderscore copy\}"}. A protected \textunderscore copy function of the
element is called in such case and for our simple \texttt{pb-clipboard} element it
provides its core \TeiEmphasisII{copy-to-clipboard} functionality. 

\begin{lstlisting}

/**
* Copy text content from the <slot> to the clipboard
*/

_copy() {
const slot = this.shadowRoot.querySelector('slot');

// first import nodes from the slot into a temporary div
const content = document.createElement('div');
slot.assignedNodes().forEach((node) => {
content.appendChild(document.importNode(node, true));
});

// copy the innerText of the temp div into the clipboard
navigator.clipboard.writeText(content.innerText);
}

\end{lstlisting} 

We glanced over yet another interesting function invoked in the \texttt{render}
method. \texttt{translate}, which accepts as an argument a key identifying a
corresponding label in i18n language files. It could be one of keys shipping with TEI
Publisher, but here, for a new component we need a more specific label, presenting the user
with a short, informative text to be displayed when hovering over \TeiEmphasisII{
copy-to-clipboard} button. Obviously, the label should change in line with the
language setting for the whole application, which is why we need the i18n module in the
first place. 

\begin{lstlisting}

title="${translate('clipboard.copy')}"

\end{lstlisting} 
Please refer to the chapter on i18n for in-depth discussion
of the subject. Here we'll just mention that additional language files for new components
should be placed in i18n/app, mimicking the location and format of
Publisher. 

\begin{lstlisting}

{
"clipboard": {
"label": "Quote  as:",
"copy": "Click to copy to clipboard"
}
}

\end{lstlisting} 
And one last job is a little bit of styling to make things pretty.

\begin{lstlisting}

static get styles() {
return css`
:host {
display: block;
}
h3 {
margin: 0;
font-size: .85em;
font-weight: normal;
color: #3a3a3a;
}
div {
display: flex;
align-items: center;
padding: 0 16px;
}
`;
}

\end{lstlisting} 
The final directive at the very bottom of pb-clipboard.js is
necessary to register the custom element with the browser. 

\begin{lstlisting}

customElements.define('pb-clipboard', PbClipboard);

\end{lstlisting} 

\subsection*{Testing pb-clipboard}

\label{custom-components-testing}
Have a look at the supplied index.html example. Run \texttt{npm
start} to run a simple \href{https://www.npmjs.com/package/es-dev-server}{local server} instance
which allows to test our developments as we work on them without bundling. 

Opening index.html with this server you can see
<pb-clipboard> in action. 

\begin{lstlisting}[language=html]

<html>
<head>
<title>Using pb-clipboard</title>
<style>
pb-clipboard {
margin-bottom: 20px;
}
</style>
<script type="module" src="src/pb-clipboard.js"></script>
</head>
<body>
<h1>Using pb-clipboard</h1>
<pb-clipboard label="Quote as:">John Doe: "The miracles of foobar", Paradise Publishers, Little Village, Stardate 46254.7</pb-clipboard>
<input type="text" name="test-clipboard" value="" size="60">
</body>
</html>

\end{lstlisting} 
In order to use the element, you need to import the component code into your HTML page,
as demonstrated with the <script> and \texttt{src="src/pb-clipboard.js"}. 

It's all that is needed to use <pb-clipboard> as any other HTML element. Its
label property is specified via \texttt{@label} attribute and the copy text is just the
text content of the element. 

Pressing the button copies the citation text from the page and, just to test, you can
paste it into the input box below.

\begin{figure}[h]
\caption{pb-clipboard in action on the es-dev-server}

\includegraphics[max size={\textwidth}{\textheight}]{pb-clipboard-action.png}

\end{figure}

\subsection*{API documentation}

\label{custom-components-api}
Implementing a new feature is only half of the task - and sometimes the easier bit. All
\texttt{ pb-components} come with their API documentation and most of them also with
one or more Demo showcases. Have a look e.g. at <pb-collapse> component for a
simple one and compare with much more elaborate sections devoted to
<pb-toggle-feature> or < pb-select-feature>. 

\begin{figure}[h]
\caption{Initial part of the API tab of pb-collapse documentation}

\includegraphics[max size={\textwidth}{\textheight}]{api-docs.png}

\end{figure}

API documentation is generated automatically by \texttt{npm docs} task. You just
need to add \href{https://www.npmjs.com/package/web-component-analyzer#%E2%9E%A4-how-to-document-your-components-using-jsdoc}{documentation-style comments} in your code. Example below illustrates how to nest
code examples or specify slots and events so they are picked by the documentation generator. 

\begin{lstlisting}

/**
* This is a documentation-style comment
*
* with code example
* ```html
* <pb-foo>
*   <slot></slot>
*   <div slot="foo-content">
*       Foo bar
*   </div>
* </pb-foo>
* ```
* slots specification:
*
* @slot - unnamed default slot
* @slot foo-content - content to be shown when foo happens
*
* events specification:
* 
* @fires pb-foo-open - Fires opening the foo section
*/

\end{lstlisting} 

\subsubsection*{Demo}

\label{custom-components-demo}
We encourage you to prepare a demo entry for each newly created component. Demo
ideally presents one or more use case examples which illustrate where and how would you
use a component. Keep the demo page simple and minimal, so other elements do not obstruct
understanding the code.

\begin{figure}[h]
\caption{Demo file for pb-clipboard}

\includegraphics[max size={\textwidth}{\textheight}]{api-docs-demo.png}

\end{figure}

Save your demo files in demo directory and register it in
demo/demos.json with the demo filename and your chosen label for
the tab (but please stick to Demo if you only have one). 

\begin{lstlisting}

"pb-collapse": {
"demo/pb-collapse.html": "Demo"
}

\end{lstlisting} 
If you supply a number of demo files, choose meaningful labels for tabs, e.g.

\begin{lstlisting}

"pb-toggle-feature": {
"demo/pb-toggle-feature.html": "Server-side with pb-view",
"demo/pb-toggle-feature2.html": "Client-side",
"demo/pb-toggle-feature3.html": "Server-side with pb-load"
}

\end{lstlisting} 

\subsection*{Bundling and distribution}

\label{custom-components-bundle}
Any new component \TeiEmphasisI{must} be explicitly imported by
pb-extension-bundle.js. 

\begin{lstlisting}

import './src/pb-clipboard.js';

\end{lstlisting} 
Run \texttt{npm build:production} to generate a distribution bundle. The generated
library (located in dist) will include everything, including the
version of the \texttt{pb-components} library you are building upon and all
dependencies. As a result, you can use it as a drop-in replacement for
\texttt{pb-components} package: in your custom project, for TEI Publisher itself or
Publisher-generated custom apps. 

\subsection*{Using pb-extension-bundle in TEI Publisher or other apps}

\label{custom-components-using}
The created library can be used as a drop-in replacement for the default \texttt{
pb-components} library. 

To do so:

\begin{enumerate}
\item {
clone \texttt{tei-publisher-app} or the generated app you would like to modify

}\item {
edit package.json and replace the dependency for 
@teipublisher/pb-components with the replacement library 

}\item {
edit build.properties and change
scripts.dir to point to the replacement library 

}\item {
call \texttt{ant} to build \texttt{tei-publisher-app}

}\end{enumerate}

For example, to use the git source of \texttt{pb-extension-template} in 
package.json, change the dependencies as follows: 

\begin{lstlisting}

"dependencies": {
"@teipublisher/pb-extension-template": "git+https://github.com/eeditiones/pb-extension-template#master"
} 

\end{lstlisting} 
then change build.properties to contain: 

\begin{lstlisting}
scripts.dir=node_modules/@teipublisher/pb-extension-template/dist
\end{lstlisting} 

Building \texttt{tei-publisher-app} should then copy scripts and resources from
\texttt{ pb-extension-template} instead of \texttt{pb-components}. 

\begin{mdframed}[frametitle={\paragraph*{Note}

}]
Make sure to adjust the repository link and name of the extension module to the one
you created. Example above assumes working directly with
\texttt{pb-extension-template} but it's unlikely to be the case in real life.

\end{mdframed}

\section*{Adding a custom vocabulary}\markboth{Adding a custom vocabulary}{Adding a custom vocabulary}

\label{new-vocabulary}
As discussed in the opening chapter, publishing a corpus of documents online is much more
than just transforming a single source document into the desired output format. To fully
support a new XML vocabulary in TEI Publisher several aspects need to be adressed:

\begin{itemize}
\item {
ODD with processing models

}\item {
default view and page template

}\item {
navigation, breadcrumbs and table of contents

}\item {
search and filtering: full text index definitions, facets and fields

}\end{itemize}

ODD and processing models within it govern how the document in your new vocabulary will be
transformed into a range of available output formats: HTML, ePub etc.

All other aspects are interconnected and depend on the understanding what constitutes the
basic unit of the text: TEI primarily considers \TeiEmphasisII{divisions} or \TeiEmphasisII{
pages}, DocBook rather \TeiEmphasisII{sections}. Therefore navigation for TEI
document will be switching between <div> s or reconstructed XML fragments between
subsequent <pb> s, while talking about pages in DocBook documents makes no sense and
< section> s are the main structural units. 

This structure has its consequences for further aspects: generating TOC in TEI will
analyze nested <div> / <head> structures but only <section> / 
<title> in DocBook. Likewise, KWIC display in TEI will be showing matches in
<div> context but <section> in DocBook, so Lucene indexes need to be
defined on these elements in their appropriate namespaces. Ditto for facets and fields used
for sorting and filtering. 

Sections below will explain where and how to customize these aspects in more
detail.

\subsection*{ODD}

\label{new-vocabulary-odd}
Create a new, blank ODD file which is not chained to any other ODD and add <
elementSpec> s for its elements. Make sure that you specify correct namespace for
your vocabulary. Optionally, you can also specify an external CSS file with style
declarations for classes and elements you will be using in processing models of your ODD. 

See how it looks in the ODD for DocBook.

\begin{figure}[h]
\caption{ODD for DocBook}

\includegraphics[max size={\textwidth}{\textheight}]{new-vocabulary-odd.png}

\end{figure}

When adding models into the custom ODD for your vocabulary it is recommended that at
least one element applies the document behaviour. Usually it will be
the top level element or the main content-bearing one (like <article> in DocBook). 

This is not strictly required but for print output via LaTeX or FO the 
document behaviour specifies default prologue governing basic setup for PDF.
If you refer to the docbook.odd you will note that the same effect is
achieved by explicitly defining the prologue in the <pb:template> for 
article. 

\subsubsection*{Case study: foo vocabulary}

\label{new-vocabulary-foo}
Let's consider an imaginary vocabulary called \TeiEmphasisII{foo}. All documents
in this vocabulary will belong to the \texttt{http://foo.io} namespace. Simple
document could look as follows: 

\begin{lstlisting}[language=xml]

<fooStart xmlns="http://foo.io">
<foo>My foo document</foo>
<bar>About something very important for foo community.</bar>
</fooStart>

\end{lstlisting} 
Let's save this document in the playground collection as
foo.xml. 

Unfortunately a request to retrieve this document in Publisher fails with
\TeiEmphasisII{the server did not return any content} error message. 

\begin{lstlisting}
http://localhost:8080/exist/apps/tei-publisher/playground/foo.xml
\end{lstlisting} 
Fixing this will require creating a new ODD for \TeiEmphasisII{foo} vocabulary. 

Create a new ODD as described previously. Use document
behaviour for <fooStart> element and perhaps <inline> with an <
outputRendition> set to italic for <foo> element.
Please note to specify the ODD for your vocabulary. 

Very bare bones ODD file for a fictional \TeiEmphasisII{Foo} vocabulary could
look as follows: 

\begin{figure}[h]
\caption{ODD for Foo}

\includegraphics[max size={\textwidth}{\textheight}]{foo-odd.png}

\end{figure}

Or, in XML form:

\begin{lstlisting}[language=xml]

<schemaSpec start="fooStart" ident="foo" ns="http://foo.io"> 
<elementSpec ident="foo" mode="add">
<model behaviour="inline">
<outputRendition>font-style: italic;</outputRendition>
</model>
</elementSpec>
<elementSpec ident="fooStart" mode="add">
<model behaviour="document"/>
</elementSpec>
</schemaSpec>

\end{lstlisting} 
With this in place we could reformulate our request to explicitly specify the ODD to
use and a single view. 

\begin{lstlisting}
http://localhost:8080/exist/apps/tei-publisher/playground/foo.xml?odd=foo&view=single
\end{lstlisting} 
\begin{figure}[h]
\caption{foo.xml rendered with foo.odd in single view}

\includegraphics[max size={\textwidth}{\textheight}]{foo-single-view.png}

\end{figure}

\begin{mdframed}[frametitle={\paragraph*{Note}

}]
It is necessary to use single view along with the
foo.odd. Otherwise, the app default view would be used, which
in TEI Publisher is normally set to div. As we already mentioned,
implementation of view parameters needs to be vocabulary-specific to work. Since
\TeiEmphasisII{ foo} vocabulary doesn't yet have navigation customized, TEI
Publisher will fall back to TEI and try to locate <tei:div> elements, which
obviously cannot be found in our test document in foo namespace. 

\end{mdframed}

\subsection*{Default view and page template}

\label{new-vocabulary-default-view}
Rendering of the document is governed by a number of parameters, particularly
view, ODD and
template : 

Even when these parameters are not explicitly specified, TEI Publisher and apps
generated from it, will fall back to the default values specified in 
modules/config.xqm. 

\begin{itemize}
\item {
ODD: \texttt{\$config:default-view}

}\item {
view: \texttt{\$config:default-view}

}\item {
template: \texttt{\$config:default-template}

}\end{itemize}

Alternative way to specify these would be using a processing
instruction in the foo.xml document itself. 

\begin{lstlisting}[language=xml]

<?teipublisher odd="foo.odd" view="single" template="view.html"?>

\end{lstlisting} 

\subsection*{Lucene configuration}

\label{new-vocabulary-lucene}
eXist-db and TEI Publisher make extensive use of Lucene indexing engine. In particular
search, navigation, sorting and filtering heavily depend on full text indexes, facets and
fields. It is therefore paramount to specify these correctly for your data
collection.

Supporting a new vocabulary, make sure to add its namespace on the <index>
element in collection.xconf. 

\begin{lstlisting}[language=xml]

<index xmlns:tei="http://www.tei-c.org/ns/1.0" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:dbk="http://docbook.org/ns/docbook">

\end{lstlisting} 
Beyond this minor adjustment, adding a new vocabulary does not differ in creation and
use of facets and fields.

\subsection*{Navigation}

\label{new-vocabulary-navigation}
We have extensively covered modifications to the ODD and page templates in earlier
chapters. In case of vocabularies without out-of-the-box Publisher support it is necessary
to customize the navigation as well. Tacit understanding of document's structure is critical
for many kinds of user interactions - from browsing through pages to creating the table of
contents.

modules/navigation.xql is the main "control room" for all tasks related
to navigation. You will note that it imports custom modules for all supported vocabularies:
\TeiEmphasisII{ TEI}, \TeiEmphasisII{JATS} and \TeiEmphasisII{DocBook}. All
requests are dispatched to specialized modules, depending on the namespace of the document
(cf.  config:document-type function). 

\begin{lstlisting}

module namespace nav="http://www.tei-c.org/tei-simple/navigation";

import module namespace tei-nav="http://www.tei-c.org/tei-simple/navigation/tei" at "navigation-tei.xql";
import module namespace jats-nav="http://www.tei-c.org/tei-simple/navigation/jats" at "navigation-jats.xql";
import module namespace docbook-nav="http://www.tei-c.org/tei-simple/navigation/docbook" at "navigation-dbk.xql";

\end{lstlisting} 
Customizing yet unsupported vocabulary will require:

\begin{itemize}
\item {
create a new navigation module for the new vocabulary (e.g. 
navigation-foo.xql ; it should implement all the functions that 
navigation.xql dispatches to; you can use
navigation-tei as a starting point for customization 

}\item {
import it into navigation.xql

}\item {
adjust config:document-type function 

}\item {
adjust nav:get-root

}\end{itemize}

\subsection*{Search}

\label{new-vocabulary-search}
Full text search is realized via the same modular approach that governs navigation.
modules/query.xql is the main "control room", dispatching requests
to functions in specialized modules. See implementation of query-db.xql
or  query-tei.xql before creating a dedicated module for your
vocabulary. Make sure to import your module into query.xql. 

\section*{Annotating Documents}\markboth{Annotating Documents}{Annotating Documents}

\label{web-annotations}
Since version 7.1.0, TEI Publisher supports annotating TEI documents via a graphic, web
based interface. This means you can enhance existing TEI documents directly within TEI
Publisher in a user-friendly environment where XML code is neatly hidden from sight when not
needed.

The annotation editor is not meant for creating documents from scratch but targets one of
the most tedious and time consuming tasks in any edition project: adding semantic, analytical or
text-critical markup to an existing transcription.

In version 9.0.0 a new, more ergonomic layout, as well as an extended feature set for curation 
of local registers have been introduced.

\begin{figure}[h]
\caption{Annotation editor in TEI Publisher v. 9.0.0}

\includegraphics[max size={\textwidth}{\textheight}]{ann-overview-v9.png}

\end{figure}

\begin{figure}[h]
\caption{Earlier version of an annotation editor}

\includegraphics[max size={\textwidth}{\textheight}]{ann-overview.png}

\end{figure}

Typical workflow for many projects will resemble the following:

\begin{enumerate}
\item {
An initial transcription is created, either manually in an XML editor, using OCR or
HTR tools like Transkribus or converted from another format, e.g. imported from Word. 
Regardless of the method, this transcription will already contain at least the basic structural markup, i.e. divisions,
headings, paragraphs etc.

}\item {
That initial transcription is gradually enriched: textual features like emphasis can
be marked, abbreviations expanded, corrections and regularizations applied; people, places
or terms appearing in the text can be explicitly tagged and linked to an authority register; dates
or measures normalized. This is an iterative process: the resulting TEI encoding is
constantly reviewed, which may result in further changes to be made.

}\end{enumerate}

Web annotations try to ease the burden of the enrichment phase by allowing editors to mark
everything directly within the user-friendly environment, closely resembling the publication
view. It is much easier to read and doesn't require half as much TEI experience as using an
XML editor. Just use your mouse to highlight the text fragment to annotate, click on the
annotation type and optionally select additional information, e.g. to link with an external
authority file.

\subsection*{Prerequisites and considerations}

\label{annotations-prerequisites}
\begin{itemize}
\item {
\TeiEmphasisI{Browsers}

The annotation editor requires a modern browser like Firefox, Chrome or a
Chrome-based browser like the newest Edge on Windows 10.

\TeiEmphasisII{Safari}
will not work due to a known bug in text selection, which Apple seems reluctant to
fix.

Directly exporting the resulting text to a directory of the user's choice, is
currently only supported in Chrome.

}\item {
\TeiEmphasisI{Division size}

The editor should work fine for texts up to the length of a journal article or
chapter. Really long texts (e.g. a whole book) will be automatically split by top
divisions, but you may still experience a recognizable time lag for long
divisions.

}\end{itemize}

Annotations have been extensively tested, and should work reliably for tagging entities
and other inline markup. You may want to keep an eye on the resulting TEI when testing
annotations on your material. We appreciate bug reports and suggestions for
improvement.

\subsection*{Annotations: the pen and paper of the digital world}

\label{annotations-rationale}
How the annotation editor works is easy to understand if you imagine reviewing a text
the old-fashioned way: print it out, then use a marker to highlight certain passages, write
corrections over the text with a pen, or scribble notes into the margin. Once back at your
computer, all the changes need to be transferred into the TEI. You may then continue with a
second round of review by printing out the results again.

Within our electronic environment, the printout corresponds to the source TEI document
and the marks and scribbles are annotations. Until you explicitely merge the annotations
into the source TEI, they will be kept separate from the document they apply to. Once
merged, a new version of the source TEI document is established and the editing process
restarts.

Notably, TEI Publisher is able to detect existing markup in the base text when it is
loaded. Any markup corresponding to a known annotation type will be recognized and displayed
as such, therefore it can be modified. In this sense it is slightly different from working
with pen and paper.

From the printout example it should be clear that you cannot change the printed text
itself (unless you had some magic paper). Accordingly, annotations are not allowed to change
the base text, i.e. the text "printed" on the screen. If you want to explicitly indicate a
correction, you can use the \TeiEmphasisII{corr} or \TeiEmphasisII{reg} annotation
type, which corresponds to the TEI encoding with choice/sic/corr or choice/orig/reg. 

You can use annotations for virtually any kind of inline markup. The only strict
requirement is that the \TeiEmphasisII{base text}, our source document, remains stable
\TeiEmphasisII{during an editing session} i.e. until annotations are merged. The
reason for that is the annotations are anchored to a certain position in the document, so
any changes to it would mean that our coordinates might suddenly point to different
fragments.

That said, there's also a special \TeiEmphasisII{edit} annotation type, which does
allow you to perform limited editing of a text. It will just "seamlessly" change the
transcription text fragment without adding any explicit markup. Nevertheless, such a change
to the TEI document is only applied when you merge and therefore establish a new base text.
The limitation is that only text fragments can be edited: the boundaries of structural
markup or annotations may not be crossed. It can be convenient for fixing a typo in a
transcription that wasn’t caught when the base text was prepared.

You also cannot use the annotation editor to modify the structural markup of the base
text, i.e. block-level elements like divs, paragraphs, headings or notes. In case you need
to change the structure, you have to merge your annotations first, saving a new version of
the TEI document and switch to an XML editor to change the XML there. The new document can
be then reloaded into the annotation editor and you can continue.

As already indicated, it is possible to handle common nested encoding structures like
<choice> or <app> as annotations. Nevertheless the inner elements, i.e.
<lem>, <rdg>, <sic>, <corr> or <orig>,
<reg>, need to have simple text content: they cannot be annotated themselves (at
least not in the current version).

\subsection*{Applying Annotations}

\label{annotations-applying}
To start annotating a document, select or upload one into the annotations collection in
TEI Publisher.

\begin{figure}[h]
\caption{Annotation playground}

\includegraphics[max size={\textwidth}{\textheight}]{ann-playground.png}

\end{figure}

Selecting any document in this collection will load the annotation view. This view is
split into distinct areas:

\begin{enumerate}
\item {
a narrow toolbar on top of the page with a group of buttons for each annotation type in the middle, 
and another group on the right hand side for document management

}\item {
the annotation view in the middle, displaying the text content to be
annotated

}\item {
a sidebar to the right, initially empty, but which comes to life once
you start making annotations; this area is used to show forms and information relevant to the current annotation

}\end{enumerate}

\begin{figure}[h]
\caption{Annotation view}

\includegraphics[max size={\textwidth}{\textheight}]{ann-init.png}

\end{figure}

To annotate a certain passage, select it with your mouse. The buttons in the center of the top toolbar now become active. Choose an annotation by
clicking the corresponding button or using a keyboard shortcut. Hovering over buttons you can see an info text with a brief description and a keyboard
shortcut.

\begin{figure}[h]
\caption{Annotation types}

\includegraphics[max size={\textwidth}{\textheight}]{ann-types.png}

\end{figure}

Depending on the chosen annotation type, a form will now appear in the right side panel. We distinguish three categories of annotations and what you
see in the right panel differs depending on the chosen annotation type:

\begin{enumerate}
\item {
"toggle" annotations, which do not need require additional information, so they simply switch an annotation on/off, e.g. for deletions or titles
(not part of the default annotation editor setup).

}\item {
analytic or text critical annotations, which may require further input from the user, e.g. a normalized date.

}\item {
semantic annotations, which are (usually) connected to an external authority, e.g. for people, places, organizations or terms.

}\end{enumerate}

These categories are not mutually exclusive but may be helpful to explain the main functional differences between the three use scenarios. 

\subsubsection*{Toggle Annotations}

\label{annotations-toggle}
Toggle annotations are immediately applied when you click the annotation button. Since
they do not need any additional input they also do not require further confirmation. Some
good candidates might be marking of titles or deletions. 

It is worth noting that it's not a textual phenomenon that constitutes a \TeiEmphasisII{
toggle} annotation versus \TeiEmphasisII{semantic} or
\TeiEmphasisII{analytic} in our simple category scheme. It is rather what kinds of
detail a particular project decides to encode or not. Encoding of titles can be a
\TeiEmphasisII{toggle} if we just decide to simply say that a text fragment is a
title. It could become a \TeiEmphasisII{semantic} annotation if we'd like to
associate it with a bibliographical reference or other detailed information. 

\subsubsection*{Analytic and Text Critical Annotations}

\label{annotations-analytic}
These annotations are not connecting to an authority reference, but typically require
further input to be made by the user. For example a <date> annotation requires
the editor to supply a normalized date, while normalizations, abbreviations and
corrections need regularized, expanded or corrected form, respectively. Apparatus entries
will require all the variant readings. For all these annotations an input form will be
shown into which such information can be entered. The exact content of the form depends on
the annotation type.

To store the annotation, you must click on the save button beneath the form after
filling the required fields.

\begin{figure}[h]
\caption{Correction}

\includegraphics[max size={\textwidth}{\textheight}]{ann-correction.png}

\end{figure}

\subsubsection*{Semantic Annotations}

\label{annotations-semantic}
Semantic annotations include markup for entities like people, places or terms. Most
editions will try to link those to a description of the entity, either provided by an
external authority file or from a local resource. In any case you will want to reference a
unique identifier to mark occurrences of the same entity throughout the edition.

When choosing a semantic annotation from the toolbar, you will therefore see an additional panel, which allows you to consult the authority file
configured for the annotation type, e.g. Geonames for places or GND for people:

\begin{figure}[h]
\caption{Annotating a person}

\includegraphics[max size={\textwidth}{\textheight}]{ann-person.png}

\end{figure}

The semantic annotation dialog displays the query results for you to choose from and the query sent initially corresponds to the text selection
made. Often this may not find the relevant entity, but you can change the query in the input field on top of the dialog and run the search again by
pressing enter.

Use the icon to the left of an entry name to select it. The reference ID of the entry will be copied into the top input field in the details panel
and a short summary of the entity should appear beneath:

\begin{figure}[h]
\caption{Right panel after selecting an entry}

\includegraphics[max size={\textwidth}{\textheight}]{ann-entity-selected.png}

\end{figure}

The ID will be used as reference in the resulting TEI, i.e. it will appear in an attribute attached to e.g. <persName> or other TEI
element. The exact mapping between an annotation type and a TEI snippet produced can be freely configured (see below).

Semantic annotations are stored in the annotation list immediately after you select an
authority entry, so you don't have to click anywhere else to confirm your choice.

\TeiEmphasisII{NB:} at times you will find that an entity doesn't yet exist in the external authority register. 
In TEI Publisher you can now also add entries to your local register. Read more on this subject in the local registers chapter.

\subsubsection*{Batch edits and suggestions}

\label{annotations-batch}
It is not uncommon that the same entity will be mentioned multiple times in a document. To simplify and speed up the editing process, the
annotation editor tries to detect other occurrences of the currently selected entity throughout the document. After choosing an entity from
the external authority, a list of potential matches is presented in the right side panel, beneath the annotation details.

The list is compiled by traversing the text shown on screen, searching for strings
which may match the same entity. The actual query used depends on the information provided by the
authority used: e.g. if the authority supplies alternative names, these will be added to
the list of strings to search for.

Each occurrence found will be presented with a little bit of the original context shown on both sides, and with an additional checkbox to the left. 
Checking it will immediately tag the corresponding passage as another instance of the same
entity. You can also check all boxes at once by clicking on the first icon (the one with double checkmarks) in the toolbar above the list.

Placing your mouse over an entry will scroll the text to the corresponding occurrence,
showing you the match in its full context to assist the revision process.

Existing annotations referencing the same entity will still be shown in the list - but with their checkbox already marked. Sometimes you may also see an occurrence
marked in red, indicating that this is an existing annotation referencing a different entity, so considered a potential inconsistency to
review. You will see such cases additionally underlined with red dots as shown below. In this example, one of the entities marked as "Oxford" points to a
different record in the authority register. To fix this by applying the currently selected entity, check the item's checkbox.

\begin{figure}[h]
\caption{Inconsistency warning}

\includegraphics[max size={\textwidth}{\textheight}]{ann-inconsistency.png}

\end{figure}

When working on a broader material, main actors and places will be often mentioned in many documents. 
It is now possible to detect potential matches across the entire collection and review and apply them individually, or even all at once.
To start the search beyond the current document use the magnifying glass icon in the \TeiEmphasisII{Occurrences} toolbar.

\begin{figure}[h]
\caption{Start search through the entire collection}

\includegraphics[max size={\textwidth}{\textheight}]{ann-corpus.png}

\end{figure}

If matches can be found in other documents, a review panel will pop up, where you can review them 
on a document-by-document and match-by-match basis. Each document is presented as a separate results page and you 
can select or deselect occurrences depending where you want annotations to be applied.

Similarly to the conventions throughout the annotation editor, color coding is used to highlight existing annotations and potential
inconsistencies. Clicking the disk icon will directly merge and save the checked annotations into the current document and remove it from the list of
items to review.

Alternatively you can click on the file's path in the header: this will open the corresponding document in a new annotation editor in a separate
browser tab. The selected annotations will be added to the document for review, but are not merged yet. You need to explicitely save them before
closing the additional tab.

Note that opening a document for review in an extra tab will also remove it from the list of pending documents in the dialog.

\begin{figure}[h]
\caption{Review matches across collection}

\includegraphics[max size={\textwidth}{\textheight}]{ann-review.png}

\end{figure}

\subsection*{Modifying Annotations}

\label{annotations-modify}
The annotation view shows a colored line beneath the text spanned by each annotation.
You can select text within an existing annotation or across multiple different ones and
apply yet another annotation to it, thus resulting in \TeiEmphasisII{nested
annotations}. However, the editor will ensure that you do not select partial
elements, for example, a range of text followed by half of a <persName>. This would
result in invalid XML, so the editor will automatically expand your selection to include the
entire <persName>.

\begin{figure}[h]
\caption{Nested annotations}

\includegraphics[max size={\textwidth}{\textheight}]{ann-nested.png}

\end{figure}

To the right of the annotated text, a colored box indicates the type of the annotation.
The sequence of boxes also indicates how annotations are nested: the ones appearing to the
right are wrapping those to the left. In the example above the "church of San Francisco" is
a reference to a place, while "San Francisco" refers to a person, a patron saint of the
church. The <persName> element is nested in the <placeName>.

Click on the colored box to see details about the annotation. For semantic annotations,
the details will include a summary of the entity drawn from the connected authority or the
local TEI register. For analytic and text critical annotations, a table is shown, listing
the corresponding attributes associated with the annotation.

\begin{figure}[h]
\caption{Annotation details}

\includegraphics[max size={\textwidth}{\textheight}]{ann-details.png}

\end{figure}

The toolbar at the bottom of the popup allows to delete or modify the annotation.
Clicking the delete button will immediately remove the annotation, without asking for
confirmation.

Clicking on the pen icon will open the annotation details in the right sidebar, where you can modify them. For semantic annotations, the authority
lookup panel will display automatically below and you can change the connected authority entry by selecting a different one.

Again, semantic annotations are applied immediately, while analytic and text critical
annotations require a click on the save button after making modifications.

\subsection*{Merge, Export, Undo and Preview}

\label{annotations-merge}
The buttons to the right side of the main toolbar provide important functions for saving etc.: \begin{figure}[h]
\caption{Toolbar}

\includegraphics[max size={\textwidth}{\textheight}]{ann-toolbar.png}

\end{figure}
\begin{description}
\item [Reload source TEI] 
This will reload the source TEI XML into the annotation view, discarding any existing annotations. Use this if you had to change the TEI in an
external editor and want to continue annotating.

\item [Merge and save annotations to TEI] 
Merges the current set of annotations into the TEI and saves it, establishing a new version of the base document. The annotation view will be
reloaded to reflect the new base.

\item [Save and export TEI to a local file] 
(Chrome only) As above, merges and saves the annotations, but additionally prompts for a local file into which a copy of the resulting TEI
will be written.

\item [Undo last change] 
Reverts the last action applied. For batch operations (if you clicked the "apply all" button above the occurrences list) this may comprise
multiple annotations. The annotation view will be reloaded and the remaining annotations are re-applied.

\item [Display preview pane] 
Shows the preview pane at the very bottom of the screen, floating above the page. Next section discusses this in  detail.

\end{description}

\subsection*{The Preview Pane}

\label{annotations-preview}
The preview pane allows you to check how the annotations you applied to the current document would change the TEI. It also provides a preview of how
the text would be displayed via one of the available ODDs. You can choose between one of four tabs, each dedicated to a specific aspect or format:

\begin{enumerate}
\item {
the resulting HTML, i.e. how your document would display in TEI Publisher if the annotations were merged, rendered through the ODD selected by
the dropdown to the right

}\item {
the TEI of the entire document if annotations were merged

}\item {
the internal JSON structure representing the annotations (for debugging purposes)

}\item {
the TEI fragments which would be changed if annotations were merged

}\end{enumerate}

What you see in the preview does not mean that the TEI source document has been already changed: it just applies the
annotations in memory, leaving the source untouched. It allows you to double check if
annotations will be applied in the correct way. When you are satisfied with the review, the merge button described in 
the previous section, will trigger the permanent change.

\begin{figure}[h]
\caption{HTML preview}

\includegraphics[max size={\textwidth}{\textheight}]{ann-preview.png}

\end{figure}

\subsection*{Named Entity Recognition}

\label{ner}
TEI Publisher includes support for detecting and tagging named entities in texts. The idea is to further simplify the work of editors when annotating documents via TEI Publisher’s web-based annotation editor by automatically identifying potential candidates for people, places etc.

For named entity recognition to be available in the web-based annotation editor, a separate Python service
is needed: clone the \href{https://github.com/eeditiones/tei-publisher-ner}{tei-publisher-ner} repository and follow the instructions in the README.

\begin{figure}[h]
\caption{NER icon}

\includegraphics[max size={\textwidth}{\textheight}]{toolbar-ner.png}

\end{figure}

\begin{mdframed}[frametitle={}]
The presentation below has been realised with an earlier version of the TEI Publisher, nevertheless everything works the same, the only difference being the position of the NER icon in the toolbar.

\end{mdframed}

One of the distinguishing features of this solution is that it makes it rather easy to train a recognition
model on your own data sets. Head over to the \href{https://www.e-editiones.org/posts/names-sell-named-entity-recognition-in-tei-publisher/}{article on e-editiones} to read more about the service, how to use it, and how to train it.

\section*{Configuring the Annotation Editor}\markboth{Configuring the Annotation Editor}{Configuring the Annotation Editor}

\label{configuring-annotation-editor}
The annotation editor is fully configurable. This includes\begin{enumerate}
\item {
the connectors used for authority lookups

}\item {
how authority entries can be extended with additional information

}\item {
how annotations are mapped to TEI elements

}\end{enumerate}

If you would like to customize the editor for your own needs, we recommend to generate a
\TeiEmphasisII{separate application just for annotation purposes}. This makes it easier
to configure and you maintain a clear separation between data which is still being worked on
and the final edition you want to show to users.

To generate a separate application for annotations, select
Admin /App Generator. In the form,
make sure to choose the ODD called "Annotations" and select "Annotation Editing" as
template.

\subsection*{Configuring Authorities}

\label{annotation-authorities}
In its current state, TEI Publisher supports the following external authorities for
entity lookup:\begin{description}
\item [GeoNames] 
\href{https://www.geonames.org/}{geonames.org} - for
places

\item [GND] 
\href{https://gnd.network/}{Gemeinsame Normdatei} via \href{http://lobid.org/}{lobid.org} - for people, organizations and
terms

\item [Metagrid] 
\href{https://metagrid.ch/}{metagrid.ch} - for people

\item [Airtable] 
\href{https://www.airtable.com/}{airtable.com} - arbitrary
entities, each corresponding to a table

\item [Reconciliation] 
\href{https://reconciliation-api.github.io/testbench/}{Reconciliation Service} - arbitrary entities, provided by any
reconciliation service

\item [KBGA] 
\href{https://theologie.unibas.ch/de/karl-barth-zentrum/gesamtausgabe/}{Karl
Barth Gesamtausgabe} - for people, organizations, terms,
abbreviations

\item [Custom] 
A custom connector, which delegates to one or more authorities, but also
searches a local TEI register

\end{description}

The HTML template defining the user interface of the annotations editor determines which
authority is used for which annotation type and can be easily adjusted. Just edit the
templates/pages/annotate.html file, which can be done in eXide (or
any editor of your choice). A simple configuration looks as follows:

\begin{lstlisting}[language=xml]

<pb-authority-lookup subscribe="transcription" emit="transcription">
<pb-authority connector="GND" name="organization" prefix="gnd"></pb-authority>
<pb-authority connector="GeoNames" name="place" user="existdb" prefix="geo"></pb-authority>
<pb-authority connector="GND" name="term" prefix="gnd"></pb-authority>
<pb-authority connector="GND" name="person" prefix="gnd"></pb-authority>
</pb-authority-lookup>

\end{lstlisting} 
Each top-level pb-authority needs at least two attributes:\begin{itemize}
\item {
a name indicating the annotation type for which it should be
used

}\item {
a connector, which selects one of the authority connectors listed
above

}\end{itemize}

In addition, you may define a prefix: this will be prepended to the
xml:id referenced by the resulting TEI element (separated by a hyphen "-"). For example, you
may want to prefix the numeric IDs received from GND with the prefix "gnd" to obtain an XML
ID like "gnd-124507514" since a number alone would not be a valid @xml:id.

Some connectors require additional configuration attributes. At the moment those are the
\TeiEmphasisII{ GeoNames}, \TeiEmphasisII{Airtable} and
\TeiEmphasisII{Reconciliation} connectors. GeoNames requires you to register a user,
whose name is given in the  user attribute and Reconciliation requires that
you specify a service URL.

The \TeiEmphasisII{Airtable}, \TeiEmphasisII{Reconciliation} and \TeiEmphasisII{
Custom} connectors are described in more detail below.

\subsubsection*{Airtable Connector}

\label{connector-airtable}
\href{https://www.airtable.com/}{airtable.com} is not an authority
file as such, but rather a commercial online database, allowing users to define their own
tables and forms. It can therefore be turned into an authority, e.g. by defining a
\TeiEmphasisII{ people} or \TeiEmphasisII{places} table and connecting it with
the airtable connector. Since any kind of data can be stored in an airtable, a slightly
more complex configuration is necessary to specify how to access relevant tables and
extract the required information. An example configuration for a single table is shown
below:

\begin{lstlisting}[language=xml]
<pb-authority connector="Airtable" name="topic" api-key="my-api-key" base="database-id" 
table="Topics" fields="Name, Variants, Definition, Term Type" label="${Name}" 
tokenize="Name, Variants" tokenize-regex="\s*;\s*"
filter="or(find('${key}', lower({Name})), find('${key}', lower({Variants})))">
<template class="info">
<h3>${Name}</h3>
<p>
${Term Type}
<br/>
${Definition}
<br/>
${Variants}
</p>
</template>
<template class="detail">
${Term Type}. ${Definition}. ${Variants}.
</template>
</pb-authority>
\end{lstlisting} 
This will retrieve authority entries from a table called 'Topics' using the columns
Name, Variants, Definition and Term Type.

\begin{description}
\item [api-key] 
The personal API key obtained from your airtable.com user profile

\item [base] 
The API key for your database

\item [table] 
Name of the table to use

\item [fields] 
A list of table column names to be retrieved as fields. Fields can be referenced
in other configuration expressions using the \texttt{\$\{column\}} notation

\item [label] 
The field or expression to use as main label when displaying authority lookup
results

\item [filter] 
The airtable formula to be used for searching

\item [template class="info"] 
An HTML fragment to show when displaying a popover with annotation details in
the annotation editor

\begin{figure}[h]
\caption{"Info" template in action}

\includegraphics[max size={\textwidth}{\textheight}]{ann-airtable-info.png}

\end{figure}

\item [template class="detail"] 
HTML fragment to show as the detailed match description in the dialog presenting
the results of querying the authority register

\begin{figure}[h]
\caption{"Detail" template in action}

\includegraphics[max size={\textwidth}{\textheight}]{ann-airtable-detail.png}

\end{figure}

\item [tokenize] 
Defines which columns should be used when searching the text for other potential
occurrences of the entity. For the search, the column values are split using the
regular expression given in tokenize-regex

\item [tokenize-regex] 
an optional regular expression used to split values before searching the text
for other occurrences. This is useful if you have variant names separated by, or ;
and each variant should be searched for separately.

\end{description}

\subsubsection*{Reconciliation Service Connector}

\label{connector-reconciliation}
Like the airtable connector described above, the \href{https://reconciliation-api.github.io/specs/latest/}{Reconciliation
Service} is not really an authority file itself. Rather, it is a communication
protocol for authority data providers originally developed for the open-source data
cleaning software \href{openrefine.org/}{OpenRefine}. The specification
is an open, \href{https://www.w3.org/community/reconciliation/}{community-maintained} standard now, and several authority data providers offer
comforming API endpoints. GeoNames, the German GND (again via lobid), Getty vocabularies
and Wikidata are some examples - find a list of current services at the \href{https://reconciliation-api.github.io/testbench/}{service testbench}.
In addition to the general attributes described above, the only additional bit of
configuration is the service URL that should be queried. You specify it in the "endpoint"
attribute:

\begin{lstlisting}[language=xml]
<pb-authority connector="Reconciliation" name="term" prefix="wd" endpoint="https://wikidata.reconci.link/api"/>
\end{lstlisting} 
This will retrieve authority entries from wikidata.

Currently, the Reconciliation connector cannot be used as a data provider for the
Custom connector described below. This will be added in a future release.

\subsubsection*{Custom Connector}

\label{connector-custom}
The custom connector delegates queries to one or more authorities, but most
importantly it creates a copy of every authority entry you select and writes it to a local
TEI register.

For many editions the information provided by an external authority will not be
sufficient. It may be incomplete, in the sense it may lack important information relevant
in the context of the edition but also many historical persons or places may not yet
appear in any authority.

Using the custom connector gives you a possibility to extend the information about an
entity, or add new ones. This works as follows:\begin{enumerate}
\item {
whenever you select an entry from the external authority, the custom connector
creates a skeleton <person>, <place> or <category> TEI
element in the local TEI registry (the exact location of the registry can be
configured) using the information provided by the authority

}\item {
you can extend the local entry with additional information, e.g. add a note to
explain why the person is important in the context of the edition

}\item {
if the custom connector has an attribute edit, users can modify or add entries to the local register using a form.
Obviously the form needs to be provided by the developer as described further below. Currently there are forms for
people, places and organizations.

}\item {
any subsequent authority query will also search the local registry and matches
found there will be ranked at the top of the results

}\item {
to support entites which do not exist in an external authority, just create an
entry in the local registry and assign it a local xml:id

}\end{enumerate}

To configure the custom connector, simply wrap it around the definition for the
external authority you want to use, e.g.:

\begin{lstlisting}[language=xml]
<pb-authority connector="Custom" name="person">
<pb-authority connector="GND" prefix="gnd"></pb-authority>
</pb-authority>
\end{lstlisting} 
This defines a custom connector for the annotation type 'person', delegating queries
to the GND connector, but also maintaining a local registry. By default the local registry
is stored in a TEI document residing in data/registry.xml. You can
change the location by modifying the variable
\$anno:local-authority-file in the annotation configuration,
modules/annotation-config.xqm. You can also change the function
rapi:insert-point to configure where exactly the local entity
definitions will be stored.

\begin{mdframed}[frametitle={}]
Currently, it is not possible to use the Reconciliation connector described above in
the context of the Custom connector. This will be added in a future release.

\end{mdframed}

\subsection*{Configuring Annotations}

\label{annotations-config}
\begin{mdframed}[frametitle={}]
TEI Publisher 9 introduces various changes to the annotation editor, including a different page layout. It also uses a sophisticated framework for forms, called \href{https://jinntec.github.io/Fore/doc/index.html}{Fore}, which is in particular used for the custom entity editors, but also powers some of the functionality of the main editor page. The user-customizable parts more or less stayed the same though, so updating an existing annotation app should be fairly easy (see the chapter on updating from 8 to 9).

\end{mdframed}
Adding new annotation types or modifying existing ones involves the following three files within TEI Publisher or generated apps:

\begin{description}
\item [templates/pages/annotate.html] 
The HTML page for the annotation editor

\item [modules/annotation-config.xqm] 
Defines how annotations are mapped to TEI

\item [odd/annotations.odd] 
The ODD used to render the annotation text view. In generated apps this will live
in resources/odd/annotations.odd.

\end{description}
Let's assume we would like to support an annotation to tag foreign language passages
with the TEI <foreign> element:

First, open templates/pages/annotate.html in eXide and locate the < div> with class header-toolbar.
This is the main toolbar and you'll find the list of annotation-action buttons in the second span.icon-group. Like
many elements in TEI Publisher, < paper-icon-button> is a webcomponent from the polymer library, which renders a button compliant with Google's
material design. You could use any other button-type element here, but for consistency, let's stick with <paper-icon-button>. We define our new
button like this:

\begin{lstlisting}
<paper-icon-button class="annotation-action toggle" title="Foreign" data-type="foreign" icon="icons:language" data-shortcut="⌘+⇧+b,ctrl+⇧+b" disabled="disabled"></paper-icon-button>
\end{lstlisting} 
\begin{figure}[h]
\caption{Configure a new annotation type}

\includegraphics[max size={\textwidth}{\textheight}]{ann-configure.png}

\end{figure}

Make sure to include all the attributes shown:

\begin{description}
\item [class] 
must at least contain annotation-action. The toggle indicates that this is a toggling annotation, which just
switches between on and off and does not need further input. For semantic annotations you can also add authority, which would
trigger the authority lookup.

\item [title] 
a label to be shown when the mouse is moved over the button.

\item [data-type] 
indicates the annotation type.

\item [icon] 
the \href{http://kevingleason.me/Polymer-Todo/bower_components/iron-icons/demo/index.html}{material design icon} to use

\item [data-shortcut] 
an optional keyboard shortcut: here we use command-shift-b for Mac and
ctrl-shift-b on windows

\item [disabled] 
initially disables the button

\end{description}
If you reload the annotation editor in the browser, you should now see your new button.
However, TEI Publisher does not yet know how to translate the new annotation into actual TEI
markup. To fix this, open modules/annotation-config.xqm and search for
the function anno:annotations. This is a long switch statement with
cases corresponding to the different annotation types. Add a new case at the top:

\begin{lstlisting}
declare function anno:annotations($type as xs:string, $properties as map(*), $content as function(*)) {
switch ($type)
case "foreign" return
<foreign xmlns="http://www.tei-c.org/ns/1.0">{$content()}</foreign>
...
};
\end{lstlisting} 
This will simply wrap a <foreign> tag around the existing content. Note that
\$content is passed in as a function pointer, so it is important to
call it as \texttt{ \$content()}. Also note how we need to declare the TEI namespace.
Without this namespace declaration, the element would not be recognized as TEI.

Now we can try our new annotation: select a passage, click on the button and see how the
text is marked as an annotation. The color is chosen automatically. You can also check in
the TEI preview pane that the annotation is correctly output as a TEI <foreign>
element.

However, if you save the annotations, you'll notice that - once the annotation view
refreshes - the foreign text is rendered in italics, but not marked as an annotation! To fix
this, we need to modify the ODD used for rendering the annotation view.

Open odd/annotations.odd (named "Annotations"), either in eXide or
the ODD editor. Add an <elementSpec> for element <foreign> with an inline
model and a cssClass containing \texttt{annotation
annotation-foreign}.

\begin{lstlisting}
<elementSpec ident="foreign" mode="change">
<model behaviour="inline" cssClass="annotation annotation-foreign"/>
</elementSpec>
\end{lstlisting} 
If you like, you can also keep the <outputRendition>, which renders the text in
italic. Key is that you declare the two \TeiEmphasisII{annotation annotation-foreign}
CSS classes, because those will tell TEI Publisher that the element should be treated as an
annotation.

As a general guideline, the ODD rules for annotations should produce simple inline tags.
They should output the content of the element without any modification. They may use <
outputRendition> to change the appearance, or supply other parameters (than 
content).

After saving the ODD, reloading the annotation editor should properly display the <
foreign> as an annotation and we can start using our new annotation type.

However, we may not be entirely happy with the simple on/off toggle: it would be much
better if we could also indicate the used language in <foreign>. This means we have
to change our annotation from a mere toggle into one which can take an additional
parameter:

To achieve this, go back to templates/pages/annotate.html and
remove the toggle class from the <paper-icon-button>:

\begin{lstlisting}
<paper-icon-button class="annotation-action" title="Foreign" 
data-type="foreign" icon="icons:language" data-shortcut="⌘+⇧+b,ctrl+⇧+b"
disabled="disabled"></paper-icon-button>
\end{lstlisting} 
We would also like to provide an input field into which the user can enter the language. Scroll down to the "Annotation Details" section in which
the <form> for the annotation types is defined and add another input on top:

\begin{lstlisting}
<iron-form id="edit-form">
<form action="">
<paper-input class="annotation-form foreign" name="lang" label="Language"></paper-input>
...
</iron-form>
\end{lstlisting} 
Again we're using a webcomponent for the input to get the material design look and feel. The class attribute is particularly important: it must
always contain annotation-form, followed by the annotation type: foreign. The name is arbitrary, but should be unique
and we need to remember it for later. The label should contain a short title, which will be shown next to the input.

Finally, we need to change our rule in
modules/annotation-config.xqm to add the new parameter to the
generated <foreign> element. Navigate to the file and change the
anno:annotations function as follows:

\begin{lstlisting}
declare function anno:annotations($type as xs:string, $properties as map(*), $content as function(*)) {
switch ($type)
case "foreign" return
<foreign xmlns="http://www.tei-c.org/ns/1.0" xml:lang="{$properties?lang}">{$content()}</foreign>
...
};
\end{lstlisting} 
The function receives all the parameters entered into the form fields in the \$properties map. In the form we used
\texttt{name="lang"}, so the corresponding value is retrieved from the map with \texttt{\$properties?lang}.

That's all. You should now be able to modify your existing foreign annotation, enter a
language and see how it is output into TEI.

\subsubsection*{Inserting an annotation before the selection}

\label{annotations-insert}
By default, the text currently selected on the page will become the content of the annotation. For some elements this is not a suitable approach.
A page beginning (<pb>) or a note would be typical examples. The editor supports this: if you add a class before to the annotation
action button, TEI Publisher will not replace the text, but insert the new annotation right before the selection:

\begin{lstlisting}[language=xml]
<paper-icon-button class="annotation-action before">...</paper-icon-button>
\end{lstlisting} 

\subsection*{Other Considerations}

\label{annotations-considerations}
Web annotations require a clear mapping between the HTML view of the text in the browser
and the TEI document in the database. It is therefore important to acknowledge the following
restrictions:

\begin{enumerate}
\item {
TEI Publisher's page-by-page display of a text will not work in the annotation
editor

}\item {
Likewise, the fill parameter, which causes TEI Publisher to fill up
short fragments with content from nested divs, should be set to 0 for annotation
purposes.

}\item {
The annotation editor can operate on documents with multiple division and will show
them one after the other. However, these need to be top-level divisions. Therefore the
depth parameter should be set to 1.

}\end{enumerate}

To ensure these conditions are met, TEI Publisher sets the following configuration for the annotate
collection in config.xqm:

\begin{lstlisting}
declare function config:collection-config($collection as xs:string?, $docUri as xs:string?) {
switch ($collection)
(: For annotations we need to overwrite document-specific settings :)
case "annotate" return
map {
"template": "annotate.html",
"overwrite": true(),
"depth": 1,
"fill": 0
}
default return
(: Return empty sequence to use default config :)
()
};
\end{lstlisting} 
Generated applications should choose similar settings. If you create a separate app just
for annotations, the following function in the config.xqm will suffice to impose the right settings for all
documents:

\begin{lstlisting}
declare function config:collection-config($collection as xs:string?, $docUri as xs:string?) {
map {
"template": "annotate.html",
"overwrite": true(),
"depth": 1,
"fill": 0
}
};
\end{lstlisting} 

\section*{Local authority registers}\markboth{Local authority registers}{Local authority registers}

\label{registers}
In TEI Publisher 9 a suggested structure for local taxonomies and registers for people, places and organizations
has been introduced in recognition of a common need in editorial projects to create and maintain such datasets.
As with virtually all other aspects of the TEI Publisher, the default solution can be fully customised, extended and tailored to the 
specific needs of the project.

\begin{figure}[h]
\caption{Default structure of the registers collection}

\includegraphics[max size={\textwidth}{\textheight}]{register-structure.png}

\end{figure}

To keep things simple, we have extracted each type of register into a separate TEI document. By default these reside in 
\texttt{data/registers} collection, but location can be changed in the \texttt{modules/config.xqm}. Below is 
the relevant excerpt from the configuration file:

\begin{lstlisting}
(:~
: The root of the collection hierarchy containing registers data.
:)
declare variable $config:register-root := $config:data-root || "/registers";

\end{lstlisting} 

The people, place and organization registers have a similar structure, utilizing a \texttt{<standOff>} as a wrapper
for \texttt{listPerson}, \texttt{listPlace} and \texttt{listOrg}, respectively. Keywords register, as is more 
fitting for this kind of ontology, uses \texttt{taxonomy} instead.

The sample below presents the general structure of the person register as well as microstructure of a sample entry. 
Since in TEI Publisher we are using the GND as the data source for annotating references to people, the local register entries
are reflecting some of the GND information, namely short biographical note, birth and death information and a list of professions.
Nevertheless, this structure can be adjusted as necessary within the project.

\begin{figure}[h]
\caption{Default encoding structure of the person register}

\includegraphics[max size={\textwidth}{\textheight}]{register-xml.png}

\end{figure}

\subsection*{Maintaining authority registers}

\label{register-maintain}
Typically, when annotating the text of the transcription we will consult an authority file, 
either an external resource like GND or VIAF, or one internal to the project to identify a reference to a place or an individual.
On the level of the TEI encoding we will be usually just adding an identifier reference to the dedicated element, like \texttt{persName}.

As it is a tedious and error prone task to provide these identifiers manually, TEI Publisher offers a 
mechanism to query authority registers, present matching results and make a selection in a user friendly interactive component
(see arrow marked as 1. on the screenshot below). 
Thanks to its functionality a connection can be made without ever typing or copying long identifiers.

\begin{lstlisting}[language=xml]
... in Altenberg <persName ref="gnd-136602592">Ambrosius Leibnütz</persName> ...
\end{lstlisting} 

As a side effect of such an operation, TEI Publisher creates a local register entry for the selected entity.

Nevertheless, from time to time an entry will not yet exist in the authority register we are using, or possibly the 
information there is incomplete or incorrect. One could edit the local register manually in such cases, but from 
TEI Publisher version 9 we now offer facilities to edit or create an entry in 
the local register (see arrows marked 2 and 3 in the screenshot) through a form-based interface. Just click on the 
\TeiEmphasisII{pencil} icon to edit the entry locally (or use \TeiEmphasisII{plus sign} icon to add a completely new one.

\begin{figure}[h]
\caption{Accessing register linking and editing functions in annotation editor}

\includegraphics[max size={\textwidth}{\textheight}]{register-edit.png}

\end{figure}

\subsubsection*{Editing a person}

\label{register-edit}
Say, we would like to add a variant name for our \TeiEmphasisII{Ambrosius Leibnütz} entry, 
and also edit and translate the German content (which was pulled automatically in from GND) into English. From the annotation 
editor we can use the \TeiEmphasisII{pencil} icon 
to open the editing form. It will appear in the right hand panel and presents form controls for 
the information stored in the register. We can edit these fields and just press the \TeiEmphasisII{save} icon when done. 
At this point new data will be stored in the local register. NB: saving obviously only works for logged in users.

The screenshot below presents a comparison of an entry freshly added to the local register from GND, and the 
same entry after edits in the TEI Publisher form.

\begin{figure}[h]
\caption{Editing a person entry}

\includegraphics[max size={\textwidth}{\textheight}]{register-change.png}

\end{figure}

You will note that this form makes use of several types of form controls: basic text fields, for name or date; 
select for choosing the gender and a custom XML editing widget to edit the note. The latter is a third-party 
web component called \texttt{jinn-xml-editor} which allows for basic edits and provides syntax checks 
and higlighting.

\begin{figure}[h]
\caption{Error message from the note editing widget}

\includegraphics[max size={\textwidth}{\textheight}]{register-jinn-xml-editor.png}

\end{figure}

\subsection*{Customizing local registers}

\label{register-customize}
Each project may have particular needs in terms what kinds of registers it needs and the exact 
microstructure the registry entries need to have. Therefore TEI Publisher proposes a modular approach 
to the subject, which allows for customizations of all aspects. Nevertheless there are several conceptual blocks 
which need careful orchestration to smoothly work together. Namely, a place to store each of the registers, 
the data model for individual entry, the data model and source code for the input form, as well as the API endpoints 
and corresponding functions for all CRUD (create, read, update, delete) operations on the register, and, last but not least, 
the hooks in the annotation template to enable all this to the user.

\begin{mdframed}[frametitle={}]
When creating a custom app with the TEI Publisher the \texttt{data/registers} collection will 
be included in the generated application. Nevertheless it is strongly recommended to move registers and other 
application data to a separate package, as discussed in data-organization chapter.

\end{mdframed}
The API endpoints for registers customization start with \texttt{/api/register} and call a set of functions from 
\texttt{modules/registers.xql}, which can be customized to reflect differences in the data 
coming from external authority and local entry structures.

As mentioned before, location of the registers is determined via \texttt{\$config:register-root} variable in \texttt{config.xqm}. 
In the same module there are further customization options related to registers: location of the models for the input forms 
(in \texttt{\$config:register-forms}) and dedicated configuration for each of the editable register types.

The actual forms themselves are located in \texttt{templates/pages/annotations} as they are effectively 
HTML files with embedded \href{https://jinntec.github.io/Fore/doc/index.html}{Fore} form webcomponents. Please consult Fore \href{https://jinntec.github.io/fore-docs}{documentation} how to customize these.

\begin{figure}[h]
\caption{Register configuration in config.xqm}

\includegraphics[max size={\textwidth}{\textheight}]{register-config.png}

\end{figure}

The \texttt{\$config:register-map} allows to determine the following information for each registry:

\begin{enumerate}
\item {
\texttt{id}: identifier by which the registry can be reached in the database, either to access 
information about existing entry or to determine the insertion point for a new one; e.g. for 
the \TeiEmphasisII{person} registry it is by default set to \texttt{pb-person} which is the @xml:id attribute of the TEI element in
\texttt{data/registers/persons.xml}

\begin{lstlisting}
<TEI xmlns="http://www.tei-c.org/ns/1.0"  xml:id="pb-persons">
\end{lstlisting} 
this identifier is always resolved in the context of the \texttt{\$config:register-root} variable 
to avoid potential conflicts

}\item {
\texttt{default}: identifier by which the default data model for an entry can be accessed; this identifier is always resolved in the context of the \texttt{\$config:register-forms}

}\item {
\texttt{prefix}: a prefix for the newly created entry, e.g. a new person will be given an id 
like \texttt{person-00015} or similar, depending how many have been created locally earlier.

}\end{enumerate}

\section*{TEI Publisher in production}\markboth{TEI Publisher in production}{TEI Publisher in production}

\label{production}
Regardless of the installation type, TEI Publisher always runs on an \href{https://exist-db.org}{eXist-db database} and there are a
few things to keep in mind for a production system, i.e. one that is publicly available to
users. We strongly suggest following the recommendations outlined in the \href{https://exist-db.org/exist/apps/doc/production_good_practice}{Production Use - Good Practice} of the eXist-db documentation. One important point is
to always run eXist-db in production behind a proxy server, which serves as an intermediary to
control and protect access to a server on which the database runs.

\subsection*{Running behind a proxy}

\label{proxy}
To set up a proxy, we suggest looking at the docker compose configuration we provide. It includes
\href{https://github.com/eeditiones/teipublisher-docker-compose/tree/master/conf}{configuration templates} for the nginx proxy. More general information about
proxy servers and eXist-db can be found in the article \href{https://exist-db.org/exist/apps/doc/production_web_proxying}{Proxying eXist-db
behind a Web Server}.

What does a proxy do for you? It can:

\begin{enumerate}
\item {
handle domains and protect parts of the database you don't want external users to access. For example, you can
access the Escher edition using its \href{https://www.briefedition.alfred-escher.ch/}{public URL} and
you will directly land on the home page of the edition. What you can't see is that the Escher is just one out of several editions hosted
within the same eXist database. It is the proxy's job to direct you to the correct application
matching the public URL, so it appears to you as if there were only one edition. Other editions in the same
database are hidden and effectively protected.

}\item {
enforce a secured connection: communication between the users browser and the proxy will be secured by
HTTPS. And because all traffic is routed through the proxy, it is safe to keep the eXist database running on HTTP.

}\item {
cache specific pages, so TEI Publisher does not need to transform TEI to HTML every time

}\end{enumerate}

In the following sections we'll discuss specific settings you should pay attention to when running TEI
Publisher behind a proxy.

\subsubsection*{Context paths}

\label{context-path}
If you would like the proxy to directly route traffic for a public URL to a specific application within
eXist, you also need to make sure that all internal application links are correctly set, depending
on the context in which the app operates. The link to "Start" (i.e. the home page of the edition) in the menu would be an
example. While you are developing the app, you want this link to point to
\texttt{/exist/apps/my-edition/} (we call this the \TeiEmphasisII{context path}).
When deploying the app to production (i.e. behind a proxy), this link should change and just point to
the root of the host. The context path should therefore be empty.

TEI Publisher based apps allow developers to control
this behaviour via a special variable in \texttt{modules/config.xqm} called
\texttt{\$config:context-path}.

The default setting for \texttt{\$config:context-path} is determined as follows:

\begin{enumerate}
\item {
if a Java system property called \texttt{teipublisher.context-path} is set, use its value as context
path

}\item {
otherwise look at the HTTP request header \texttt{X-Forwarded-Host} and if present, assume that
we're running behind a proxy and the context path should be empty

}\item {
finally, try to determine the context path by checking the install location of the application within
eXist. This will lead to a context path like \texttt{/exist/apps/my-edition/}

}\end{enumerate}

This procedure should work for most cases, so manually adjusting \texttt{\$config:context-path} should
rarely be necessary.

\subsubsection*{Caching}

\label{caching}
While you can use a proxy to cache arbitrary contents based on timeouts and cache expiration, TEI
Publisher 8 includes some support for a more intelligent caching approach: if enabled, TEI Publisher will
answer to the \texttt{If-Modified-Since} HTTP header sent by the proxy. If any of the resources targetted
by the request have been modified since the given timestamp, TEI Publisher will process the request as usual.
However, if it finds that no modifications were applied in the meantime, it simply returns a 304 response
code, telling the proxy that it can safely use its cached version.

To enable this feature, set the variable \texttt{\$config:enable-proxy-caching} to true.

\begin{mdframed}[frametitle={}]
At the time of writing, only the most important API calls in TEI Publisher support
\texttt{If-Modified-Since}. Those include the API call for displaying a single page or division, which
is the most frequently called operation.

\end{mdframed}

\subsection*{Hosting}

\label{hosting}
Where and how to host a custom edition built with TEI Publisher is one of the most frequent questions we
receive. Fortunately there are various options and we're doing our best to help academic users by providing
various tools to simplify the task, as well as cooperating with providers.

Some options are:

\begin{description}
\item [dedicated server] 
means a physical or virtual machine on which eXist-db, TEI Publisher and a proxy server can be
installed and configured. Many academic providers and
research infrastructures (e.g. Huma-Num) routinely support dedicated eXist-db and TEI Publisher
installations while others can do so upon request.

\item [dockerized installation] 
we provide a ready-to-use configuration including TEI Publisher, a proxy and the named entity
recognition service in the \href{https://github.com/eeditiones/teipublisher-docker-compose}{teipublisher-docker-compose} Github repository. The readme describes how to customize this
configuration for your own custom edition.

To use this option you need to find a hosting provider, which supports running a dockerized
architecture with \TeiEmphasisII{docker compose} (just search for a virtual cloud server with docker
preinstalled). Fortunately this is quite common and - unless you intend to
run a heavy duty service – the costs are very acceptable. With this option,
rebuilding the entire setup is quick and easy, which makes it the perfect solution for sites still being
under development. On the downside, performance may not be as good as with a dedicated server, but it is
hard to give any reliable figures. You'll have to see yourself. 

\item [static site] 
the newest kid on the block: instead of running TEI Publisher, eXist etc., you can transform your
custom edition into a static site. This means that the entire application is converted to a pregenerated
set of static HTML pages and helper files. The generated files can be hosted on any web server, including
free services like GitHub Pages. It is a particularly fitting solution for smaller editions without extensive
search features. The article \href{https://www.e-editiones.org/posts/community-event-going-static/}{Generating a
high voltage site by going static} describes how such a static site can be generated
and discusses in detail the advantages and drawbacks of this solution.

\item [all-inclusive hosting options] 
in cooperation with e-editiones, \href{https://www.archives-online.org/}{Archives Online} provides a complete hosting solution for scholarly
editions based on TEI Publisher and IIIF on \href{https://sources-online.org/}{sources-online.org}. This covers long-term maintenance and
support of an edition project. If you are interested in having an edition hosted, please contact \href{info@archives-online.org}{Archives Online}.

\end{description}

\subsection*{Web components}

\label{web-components}
By default TEI Publisher and apps generated from it load the user interface components from a global CDN
(content delivery network). For a long time this was the generally recommended approach. CDNs promised
reliability and fast, globally distributed access to resources. Web browsers can cache those resources
efficiently across applications.

However, we recently experienced more and more difficulties with some CDN, in particular the one used by TEI
Publisher by default. As a result, pages may appear inaccessible or slow to users, even though TEI Publisher itself is
responsive and fast.

For production deployments we therefore recommend to consider self-hosting the required component libraries.
This means: all javascript libraries are downloaded and bundled with your custom application. The build scripts
shipped with TEI Publisher and generated apps make this rather easy. The necessary steps are as follows:

\begin{enumerate}
\item {
make sure you have \href{https://nodejs.org}{nodejs} with npm
installed; also check if the build property \texttt{npm} in your
\texttt{build.xml} (for generated apps) or \texttt{build.properties} (TEI Publisher app) points to
the npm binary.

}\item {
edit modules/config.xqm and change the value of variable
\texttt{\$config:webcomponents} to "local":

\begin{lstlisting}
declare variable $config:webcomponents := "local";
\end{lstlisting} 

}\item {
build your application package with the command \texttt{ant xar-local} (instead of just calling
ant) and deploy as usual

}\end{enumerate}

\end{document}

