<?teipublisher odd="docbook.odd" template="documentation.html" depth="2" fill="2" media="print fo epub markdown"?><?xml-model href="https://cdn.docbook.org/schema/5.0/xsd/docbook.xsd" type="application/xml" schematypens="http://www.w3.org/2001/XMLSchema"?><article xmlns="http://docbook.org/ns/docbook" xmlns:xlink="http://www.w3.org/1999/xlink" version="5.0" xml:lang="en" label="c">
  <info>
    <title>Reference Manual</title>
    <author>
      <orgname>TEI Publisher Community</orgname>
    </author>
    <abstract>
      <para>In-depth documentation of features like TEI Processing Model, HTML templating, themes and layout etc.</para>
    </abstract>
    <keywordset role="genre">
      <keyword>Documentation</keyword>
    </keywordset>
  </info>
  <section xml:id="intro">
      <title>Introduction</title>
      <para><link xlink:href="tldr.xml">TL;DR</link>: shortcut for the impatient reader</para>
      <para><link xlink:href="quickstart.xml">Quickstart</link>: gentle introduction for the beginner</para>
      <para>TEI Publisher reference manual covers various aspects and technical layers of creation, customization and maintenance of publications based on data encoded primarily in XML. In particular, but not exclusively, we will be discussing <emphasis>scholarly</emphasis> publications based on data encoded in TEI.</para>
       <note><para>This introductory chapter provides a gentle overview of motivations and rationale behind Jinks and TEI Publisher design. For hands-on, technical discussion of particular topics, skip directly to the relevant chapters.</para></note>
    
    <para>Bridging the gap between a computer-processable representation of sources and tangible, published edition is not a trivial step. It involves precise analysis and modeling, tedious work, and careful orchestration across multiple layers of the technological stack. From the raw data, to the publication - be it an online website or a printed volume - there are many ways to approach the challenge from the technical perspective. For the scholars and content curators, the challenge is rather seen as an obstacle: lengthy, cumbersome and risk-laden but unavoidable process.</para>
    <figure>
        <title>XML data transformed to output with TEI Publisher</title>
        <mediaobject>
          <imageobject>
            <imagedata fileref="tp-diagram.jpg"/>
          </imageobject>
        </mediaobject>
      </figure>
    <para> It's not easy to find a way to reconcile the variety and allow for the flexibility within a shared, standards-based framework. From afar, there are significant overlaps between all scholarly publications. Yet the closer we look, the more we notice differences, from subtle to quite fundamental. After all, where is the common ground between a collection of Renaissance correspondence, Buddhist inscriptions, anthology of inaugural poems, and a lexicon of ancient individuals, of whom we only know a few words from their tombstones? Is there a way to accommodate the needs and wishes of editors, at the same time taking into account the technical and economic sustainability, as well as future re-use and interoperability of the scholarly datasets?</para>
    <para>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. The solution is based on several foundational principles:</para>
    <variablelist>
      <varlistentry>
        <term>divide and conquer</term>
        <listitem>
          <para>Split complex problems into smaller tasks. This is reflected in modular design at all levels.</para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>do not reinvent the wheel</term>
        <listitem>
          <para>Interface with existing systems and libraries where solutions already exist.</para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>standardize where you can</term>
        <listitem>
          <para>Based on open standards: from well-documented XML vocabularies (like TEI, JATS, DocBook) and formats (JSON) for the representation of data, to support for widely used protocols and specifications (e.g. Open API Specification, IIIF, DTS).</para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>customize where you must</term>
        <listitem>
          <para>Never force a concrete solution: all elements are designed as customizable.</para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>community-driven</term>
        <listitem>
          <para>TEI Publisher framework features and components are a response to real needs of user community: developed to provide a generalized solution to a repeated practical requirement.</para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>open source</term>
        <listitem>
          <para>All components are released under open licenses, assuring that all work continues to benefit the entire community.</para>
        </listitem>
      </varlistentry>
    </variablelist>
    <section xml:id="jinks">
    <title>Jinks: edition in few clicks</title>
    <para>With the <link xlink:href="quickstart.xml?id=intro-jinks#intro-jinks">Jinks</link> application manager, the core TEI Publisher idea of assembling an edition from the modular "lego" blocks is taken to the next level. The core of TEI Publisher is now decomposed into a set of small, modular profiles, which can be combined and configured to assemble concrete applications. Each profile provides end-to-end implementation for a particular aspect of a digital edition, e.g. support for a certain input format, integration of facsimile images, timelines or map display. Check the <link xlink:href="quickstart.xml?id=using-jinks#using-jinks">hands-on tutorial</link> for a walk through.</para>
    <para>Using Jinks is very simple on the surface, nevertheless it operates over the complex, heterogeneous spectrum of conceivable scholarly projects. Therefore it still requires from the user the usual intellectual and scholarly rigour to assure the end result matches the expectations. Similarly, to customize or create a new feature profile, the understanding of the orchestration across the technical layers is necessary.</para>
    </section>
     
  </section>
  <section xml:id="data-organization">
    <title>Data</title>
    <para>Applications generated by Jinks/TEI Publisher will refer to a <filename>data</filename>
      collection, where XML files are expected to be stored. A default exists, placing this collection 
      within the application package, to make the prototyping fast and smooth, 
      nevertheless the setting can be easily changed in the 
        <filename>config.json</filename> configuration file.</para>
    <para>Separating your data from application code has many benefits, particularly for actively developed applications and larger data sets. 
    This way the application code can be modified and deployed without redeploying and reindexing the data, and vice versa. It is also easier to maintain separate repositories (e.g. in Git) and differentiate access and privileges for editorial and development teams.</para>
    <para>
        As a rule of thumb it is recommended to separate data and code, nevertheless some projects may prefer to keep their data and application integrated in a single package for the sake of marginally easier distribution.</para>

    <para>A series of configuration
      properties within the <code>defaults</code> section determines where data is expected to be available:</para>
    <variablelist>
      <varlistentry>
        <term><code>data</code></term>
        <listitem>
          <para>specifies the location of the entire data collection. It can be an absolute (starting with the database root) or a relative path (specified in relation to the application collection). By default this is set to <code>data</code> subcollection of the application package.</para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term><code>data-default</code></term>
        <listitem>
          <para>Typically, the digital publication contains not only the primary dataset, for example the edited documents collection, but also a number of auxiliary resources: editorial introduction, bibliography, registers of places and people, as well as other ancilliary material. These complementary resources usually, should not appear in the
            document list the user is presented when browsing the main dataset. The <code>data-default</code> property exists to define the entry point to the edition, i.e. specify the subcollection which users should see. If such distinction is not necessary, this property can be set to the empty string.
            </para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term><code>register-root</code></term>
        <listitem>
          <para>Relative or absolute path pointing to the collection containing register data (entity lists) for people, places etc. If relative it will be resolved relative to <code>data</code>.</para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term><code>data-exclude</code></term>
        <listitem>
          <para>An array of XPath expressions pointing to documents to be filtered out when browsing documents. Use this to hide certain documents in browsable collections.</para>
        </listitem>
      </varlistentry>
    </variablelist>
     <note>
      <para>Example: the <productname>Serafin Correspondence</productname> blueprint comes with
      three subcollections under <filename>data</filename>: <filename>auxiliary</filename> contains
      a general project description, <filename>letters</filename> hosts the actual letters, and
        <filename>registers</filename> contains entity lists (as the <productname>Entity
        Registers</productname> profile expects). Obviously users should only see the
      letters when browsing documents. Therefore, <code>data-default</code> is set to
        <code>letters</code> in <filename>config.json</filename>.</para>
                </note>
    
    <section xml:id="data-package">
      <title>Creating a data package</title>
      <para>Keeping data and application code together is fine for initial
        prototyping. However, as mentioned before, it is highly recommended to separate the data from the application code.</para>
      <para>From the database and development workflow perspective, separating data and application means that you maintain
        a dedicated data repository, distributed as a xar package for eXist-db and stored in a particular collection. 
        This collection will be referenced by your application. Just like the  application package, the data package can be 
        downloaded, distributed and installed into another eXist-db.</para>
      <para>To create a data package, start a new app configuration in Jinks, fill out the
        abbreviation and the other two required form fields, and in the 
          <guilabel>Profiles</guilabel> tab, select <guilabel>Data Package</guilabel> as the base
        profile. Click on <guibutton>Apply</guibutton> and wait for the package to be created. Next, use
        the <guilabel>Files</guilabel> tab to add your data into its pregenerated
          <filename>data</filename> subcollection.</para>
      <para>After preparing your data package, you'll have to configure your application to use
        it. Open the main application in Jinks and change the <code>data</code> property (and
          <code>data-default</code> if necessary) to use an absolute path pointing to the location of
        the data within the data package. For example:</para>
      <programlisting language="json" xml:space="preserve">{
  …
  "defaults": {
    "data": "/db/apps/barth-data/data",
    "data-default": ""
  },
  …
}</programlisting>
    </section>
    <section xml:id="hierarchical-collections">
      <title>Hierarchical data collections</title>
      <para>Many editions will simply present a flat list of documents, e.g. a collection of
        letters, monographs or plays. The structure of the data is therefore very simple, all the
        files are stored on the same level in the <code>data-default</code> collection. </para>
      <para>Other publications, particularly those including heterogeneous material may require a
        more complex organization. The <productname>TEI Publisher Documentation and
          Demo</productname> app is a good example – its data is further divided into a number of
        subcollections, containing the documentation, demo documents, JATS and DOCX samples etc.
        This is reflected in the user interface: the browsing view at the top level shows several panels and users can
        navigate to the corresponding subcollections by clicking on them.</para>
      <para>In general, TEI Publisher applies the following rules for the browse
        page:</para>
      <procedure>
        <step>
          <para>if the collection to display contains a <filename>collection.html</filename>
            document, this file will be displayed</para>
        </step>
        <step>
          <para>otherwise, TEI Publisher compiles a paginated list of all documents stored in the
            collection directly and in any subcollections, no matter how deep they are nested</para>
        </step>
      </procedure>
      <para>For example, the TEI Publisher Documentation and Demo adds a
          <filename>collection.html</filename> to the data root.</para>
      <para>
                <filename>collection.html</filename> may contain an arbitrary HTML fragment (well-formed
        XML!) and may include template expressions. However, navigating to a collection is handled
        by Javascript, so links to subcollections require that a
          <filename>data-collection</filename> attribute is present, containing the relative link to
        the collection.</para>
      <para>For example, let's assume a hypothetical application with two main collections: prints
        and manuscripts. It may include the following <filename>collection.html</filename>:</para>
      <programlisting language="html" xml:space="preserve">&lt;div class="collection"&gt;
    &lt;h3&gt;Custom landing page demonstrating sub-subcollections.&lt;/h3&gt;
    &lt;ul class="documents thumbnails"&gt;
        &lt;li class="document"&gt;
            &lt;div class="thumbnail"&gt;&lt;img src="prints.png" width="128"/&gt;&lt;/div&gt;
            &lt;div class="document-info"&gt;
                &lt;h3&gt;&lt;a href="#" data-collection="prints"&gt;Prints&lt;/a&gt;&lt;/h3&gt;
                &lt;p&gt;This one is for prints.&lt;/p&gt;
            &lt;/div&gt;
        &lt;/li&gt;
        &lt;li class="document"&gt;
            &lt;div class="thumbnail"&gt;&lt;img src="manuscripts.png" width="128"/&gt;&lt;/div&gt;
            &lt;div class="document-info"&gt;
                &lt;h3&gt;&lt;a href="#" data-collection="manuscripts"&gt;Manuscripts&lt;/a&gt;&lt;/h3&gt;
                &lt;p&gt;This one is for manuscripts.&lt;/p&gt;
            &lt;/div&gt;
        &lt;/li&gt;
    &lt;/ul&gt;
&lt;/div&gt;</programlisting>
      <para>resulting in the following display:</para>
      <figure>
        <title>Fragment of the subcollections landing page</title>
        <mediaobject>
          <imageobject>
            <imagedata fileref="data-subcollection-landing.png" width="512px"/>
          </imageobject>
        </mediaobject>
      </figure>
    </section>
    
    <section xml:id="pi-config">
      <title>Processing instructions</title>
      <para> 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
          <filename>translation.html</filename>, the ODD <filename>dantiscus.odd</filename>, and
        switches to a page-by-page display (along TEI page break boundaries): </para>
      <programlisting language="xml" xml:space="preserve">&lt;?teipublisher template="translation.html" odd="dantiscus.odd" view="page"?&gt;</programlisting>
      <para>When viewing the document by structural divisions, two additional settings control the
        amount of content displayed at a time:</para>
      <programlisting language="xml" xml:space="preserve">&lt;?teipublisher depth="2" fill="6" odd="dta.odd"?&gt;</programlisting>
      <variablelist>
        <varlistentry>
          <term>odd</term>
          <listitem>
            <para>The ODD file to use for rendering the document.</para>
          </listitem>
        </varlistentry>
        <varlistentry>
          <term>template</term>
          <listitem>
            <para> The HTML view template to use. Default is <code>view.html</code> as configured in
                <filename> modules/config.xqm</filename>. </para>
          </listitem>
        </varlistentry>
        <varlistentry>
          <term>view</term>
          <listitem>
            <para> Default view to show when browsing the document. Supported values are <parameter>
                div</parameter>, <parameter>page</parameter> or <parameter>single</parameter> : </para>
            <orderedlist>
              <listitem>
                <para>
                  <parameter>div</parameter> : displays one structural division (TEI div, DocBook
                  section …) at a time </para>
              </listitem>
              <listitem>
                <para>
                  <parameter>page</parameter> : displays the document page by page. This requires
                  page break indicators to be present (<tag>pb</tag> in TEI, not supported for
                  DocBook). </para>
              </listitem>
              <listitem>
                <para>
                  <parameter>single</parameter> : the entire document (or a selected fragment of it)
                  is displayed at once </para>
              </listitem>
            </orderedlist>
          </listitem>
        </varlistentry>
        <varlistentry>
          <term>depth</term>
          <listitem>
            <para> 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.
                <tag>depth</tag> 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. </para>
          </listitem>
        </varlistentry>
        <varlistentry>
          <term>fill</term>
          <listitem>
            <para> 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 <tag>fill</tag>
              paramter defines the number of elements which should at least be present on a page. If
              not, the software tries to fill it up. </para>
          </listitem>
        </varlistentry>
        <varlistentry>
          <term>media</term>
          <listitem>
            <para>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 <code>web</code> is always assumed to work and does not need to be
              specified. Other supported output media types are:</para>
            <itemizedlist>
              <listitem>
                <para>epub</para>
              </listitem>
              <listitem>
                <para>print</para>
              </listitem>
              <listitem>
                <para>fo</para>
              </listitem>
              <listitem>
                <para>latex</para>
              </listitem>
            </itemizedlist>
            <para>For example, this documentation uses the following settings in its processing
              instruction:</para>
            <synopsis language="xml">media="latex print fo epub"</synopsis>
          </listitem>
        </varlistentry>
      </variablelist>
    </section>
    
    
  </section>
  
  <section xml:id="development-workflow">
    <title>Development Workflows</title>
    <para>This chapter discusses the different ways to interact with the database while you are
      developing your own digital edition. In essence, one can distinguish two basic approaches:<orderedlist>
        <listitem>
          <para>development is primarily done inside the database using tools like eXide, Jinks or
            oXygen</para>
        </listitem>
        <listitem>
          <para>main development takes place in a local directory using whatever editor and tools
            you prefer</para>
        </listitem>
      </orderedlist></para>
    <para>In reality, you will likely mix both. For example, even if you are mainly working in a
      directory, you may still want to use the visual ODD editor, occasionally update the
      application with Jinks etc. You therefore need ways to sync from database to file system and
      the other way around.</para>
    <para>But whichever way you choose, it is important to always have an up to data backup in a
      safe place in case anything goes wrong. The best way to achieve this is to use a versioning
      system like git. We strongly recommend to set up a git repository whenever you start work on a
      digital edition. For beginners, a graphical git client like <link xlink:href="https://github.com/apps/desktop">GitHub Desktop</link> might
      be the best choice.</para>
  <section xml:id="development-workflow-in-database">
    <title>Approach 1: Developing inside the Database</title>
    <para>This will be the easier approach as it does not require additional tooling (except for git
      – see below). It will work perfectly fine if:<itemizedlist>
        <listitem>
          <para>you are mainly interested in changing the presentation of the data via ODD and TEI
            Processing Model</para>
        </listitem>
        <listitem>
          <para>your application can rely on the existing profiles and requires only minor
            customization by changing the configuration in Jinks</para>
        </listitem>
        <listitem>
          <para>you do not need (or only very little) custom CSS, javascript or additional API
            endpoints</para>
        </listitem>
      </itemizedlist></para>
    <para>If those conditions apply, you will mostly work with the visual ODD editor (for addressing
      the presentation) and Jinks for theming and other configuration changes. If you have to add
      single source files (like CSS styles), eXide provides a reliable editor.</para>
    <para>However, it is vital to keep an up to date copy of your application somewhere save. Jinks
      itself provides two actions for retrieving a copy (see the bottom toolbar):</para>
    <variablelist>
      <varlistentry>
        <term><guilabel>Download</guilabel></term>
        <listitem>
          <para>Packages the application into a single archive (a so called XAR), which you can
            later re-install into eXist-db using the Package Manager in the Dashboard. This is a
            quick choice to get a fully functional copy or for passing the application on to other
            people to try out.</para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term><guilabel>Sync</guilabel></term>
        <listitem>
          <para>Synchronizes the file hierarchy into a local disk directory. Note that
              <emphasis>local</emphasis> means the machine where eXist-db is running. If you are
            using docker, the directory will be <emphasis>inside</emphasis> the docker image. If you
            connect to a remote server, it will be a directory on the server. Sync therefore is
            particularly convenient to use during development, to create snapshots to be committed
            to the source control repository, like Git.</para>
        </listitem>
      </varlistentry>
    </variablelist>
    <para>Because <guilabel>Sync</guilabel> won't work for everyone, let's start with the
        <guilabel>Download</guilabel> option: running the action will result in a file ending with
        <filename>.xar</filename> being downloaded to your browser. This is a normal ZIP archive and
      you can use standard utilities to extract the files into a directory of your choice. If your
      system does not recognize the <filename>.xar</filename> as a ZIP and refuses to process it,
      simply change the file ending.</para>
    <note>
      <para>Contrary to an ordinary ZIP file, a <filename>.xar</filename> has a standardized
        internal structure and comes with metadata, which informs eXist-db about how to install the
        data, create indexes and so on.</para>
    </note>
    <para>The extracted archive contains everything, which would be required to restore the current
      state of the application. At this point, we strongly recommend to initialize this directory as
      a git repository and push it to a service like Github.</para>
      <para>You can also rebuild the <filename>.xar</filename> – e.g. after making local changes to
        files – <link linkend="development-workflow-building">using the build scripts</link> included in the archive. The build step will result in
        another, updated <filename>.xar</filename> being written into the <filename>build</filename>
        subdirectory and you can install this new archive into any
          <productname>eXist-db</productname> using the <productname>dashboard</productname> (or
        command line utility like <productname>xst</productname>, see <link linkend="development-workflow-links">below</link>).</para>
  </section>
  <section xml:id="development-workflow-local">
    <title>Approach 2: Developing in a local directory</title>
    <para>If an application reaches a certain complexity, you may prefer to switch to a
        directory-first approach. This is also how TEI Publisher itself is developed. The
        advantages:</para>
      <itemizedlist>
        <listitem>
          <para>you have a safe copy of your work in a local directory at any point</para>
        </listitem>
        <listitem>
          <para>you can immediately commit changes to git or undo them later if needed</para>
        </listitem>
        <listitem>
          <para>you can use any tools you like, including the editor of your choice</para>
        </listitem>
      </itemizedlist>
      <para>If you make your changes in a directory first, you obviously have to synchronize them to
        the database. The easiest way to do so is to rebuild the <filename>.xar</filename> every
        time and install it via the <productname>dashboard</productname>. However, reinstalling the
        entire application may take a while and therefore slow you down.</para>
      <para>You can also upload single files using eXide, the file browser in jinks or oXygen's
        eXist-db integration. But again, this is a manual process.</para>
      <para>Therefore, most TEI Publisher developers prefer using a development environment (IDE)
        like Visual Studio Code, Cursor or Antigravity. They all allow you to install an
        <link xlink:href="https://open-vsx.org/extension/eXist-db/existdb-vscode">eXist-db extension</link>, which – apart from providing XQuery language support –
        comes with a helpful synchronization utility. Applications generated by Jinks already
        contain the necessary configuration (in file <filename>.existdb.json</filename>) to run this
        synchronization utility.</para>
    <figure>
      <title>Cursor editor with active sync task in bottom panel</title>
      <mediaobject>
        <imageobject>
          <imagedata fileref="cursor-sync.png"/>
        </imageobject>
      </mediaobject>
    </figure>
      <para>Once activated, the sync utility will continously watch for changes in the monitored
        directories and synchronize them to the database.</para>
      <para>While convenient, there are some caveats of this approach:</para>
      <itemizedlist>
        <listitem>
          <para>if you use the visual ODD editor, you need to download the modified ODD yourself as
            it only exists in the database</para>
        </listitem>
        <listitem>
          <para>if you modify the application configuration in jinks and apply it, there will likely
            be changes to files in the database, but not in your local directory</para>
        </listitem>
      </itemizedlist>
      <para>In those cases, use either the <guilabel>Sync</guilabel> action to automatically sync
        from database to local directory, or download a fresh <filename>.xar</filename> and unpack
        it manually.</para>
      <note>
        <para>Note, however, that if you have the sync task running in your editor, replaced files
          will be again written into the database. While this does usually not cause much damage, it
          is better to stop the task temporarily.</para>
      </note>
  </section>
    <section xml:id="development-workflow-building">
      <title>Building</title>
      <para>To build an application, you at least need to have <link xlink:href="installation.xml?id=java">Java</link> and the build tool <link xlink:href="https://ant.apache.org/">Apache Ant</link>. Both should be installed so they
        are found in your environment if you open a terminal or shell. Typing <code>ant</code>
        should produce output similar to the following: </para>
      <programlisting>Buildfile: /Users/wolfgang/Downloads/serafin/build.xml

clean:

release.true:

release.false:
     [echo] Not a release, moving on ...

check-release:

git.revision:

prepare:
    [mkdir] Created dir: /Users/wolfgang/Downloads/serafin/build/tp-serafin-1.0.0
     [copy] Copying 245 files to /Users/wolfgang/Downloads/serafin/build/tp-serafin-1.0.0

xar:
      [zip] Building zip: /Users/wolfgang/Downloads/serafin/build/tp-serafin-1.0.0.xar

all:

BUILD SUCCESSFUL
Total time: 0 seconds
      </programlisting>
      <para>Expert: if you would like to run the test suite or provide a <link xlink:href="web-components-loading">local copy of TEI Publisher's
        webcomponents</link>, you'll also need to have <link xlink:href="https://nodejs.org/en">nodejs</link> with the <code>npm</code> command 
        available in your terminal.</para>
    </section>
    <section xml:id="development-workflow-links">
      <title>Useful Resources</title>
      <para>Here are links to some of the utilities mentioned above:</para>
      <variablelist>
          <varlistentry>
            <term><link xlink:href="https://github.com/eXist-db/xst">xst</link></term>
            <listitem>
              <para>A command line interface to eXist-db, which allows you to install/remove <filename>.xar</filename> packages,
              browse collections, upload single files and more.</para>
            </listitem>
          </varlistentry>
          <varlistentry>
            <term><link xlink:href="https://www.npmjs.com/package/@teipublisher/jinks-cli">jinks-cli</link></term>
            <listitem>
              <para>Control Jinks from the command line: supports creating/updating applications from profiles, running actions etc.</para>
            </listitem>
          </varlistentry>
        <varlistentry>
          <term><link xlink:href="https://open-vsx.org/extension/eXist-db/existdb-vscode">eXist-db VSCode Extension</link></term>
          <listitem>
            <para>Adds XQuery language support and a sync task to Visual Studio Code and other IDEs derived from it</para>
          </listitem>
        </varlistentry>
        <varlistentry>
          <term><link xlink:href="https://github.com/apps/desktop">GitHub Desktop</link></term>
          <listitem>
            <para>A graphical client to create and manage git repositories</para>
          </listitem>
        </varlistentry>
      </variablelist>
    </section>
  </section>
  <section xml:id="odd">
    <title>TEI Processing Model</title>
    <para>TEI Publisher derives its name from TEI and the TEI Processing Model (TEI PM). TEI
      Processing Model is a part of the standard TEI vocabulary and TEI ODD specification format. It
      is described in the <link xlink:show="new" xlink:href="https://tei-c.org/release/doc/tei-p5-doc/en/html/TD.html#TDPMPM">Documentation
        Elements</link> chapter of the TEI P5 Guidelines. Here we discuss it at length from a
      practical perspective, including TEI Publisher specific extensions and edge case examples. For
      hands-on introduction to this topic you may want to follow the <link xlink:href="quickstart.xml?id=pm-tutorial">Quickstart</link> tutorial.</para>
    <para>TEI Processing Model specification uses 
      TEI ODD syntax to define how an XML document should be transformed.
      TEI ODD (short for One Document Does it All) was originally designed to
      provide formal, machine actionable documentation of the project in the TEI language itself. Processing models in the ODD 
      add a powerful mechanism, through which you can control
      the transformation of the source XML documents to all 
      output formats: HTML, ePUB, PDF etc. </para>
      <para>The processing model approach is flexible and media-agnostic: behaviours and rendition styles are transparently translated into different output media types. A single ODD can handle a multitude of heterogeneous source documents and various output media types with very little adjustment.</para>
        <figure>
          <title>TEI PM based transformation workflow</title>
          <mediaobject>
            <imageobject>
              <imagedata fileref="pm-transformation.jpg"/>
            </imageobject>
          </mediaobject>
        </figure>
    
    <section xml:id="pm-concepts">
    <title>TEI Processing Model transformations</title>
     <para>TEI Processing Model allows us to express even <emphasis role="bold">very complex</emphasis> requirements for processing, including the <emphasis role="bold">distinctions in processing</emphasis> based on the <emphasis role="bold">document and application context</emphasis>. For each of the markup tags we need a specific handling, we must only provide an <code>elementSpec</code> with one or more nested <code>model</code> specifications.</para>
     <para>The code fragment below shows <code>elementSpec</code> definitions and <code>model</code>s that TEI Publisher uses for a few TEI elements: <code>ab</code>, <code>add</code> and <code>app</code>.</para>
    
        <figure>
          <title>Example of TEI PM syntax</title>
          <mediaobject>
            <imageobject>
              <imagedata fileref="pm-teipublisher.jpg"/>
            </imageobject>
          </mediaobject>
        </figure>
    
    <section xml:id="pm-models">
    <title>Models, behaviours and renditions</title>
   <para>Every <code>model</code> must specify a <code>behaviour</code>, which often is one of the most common: <code>inline</code>, <code>block</code>, <code>alternate</code>, <code>link</code> or <code>note</code>. Many of the behaviour names are easily understandable, referring to basic web typesetting concepts: <code>link</code>, <code>block</code>, <code>heading</code> or <code>inline</code>. Others, e.g. <code>pass-through</code> or <code>webcomponent</code>, may require a word of explanation. <link xlink:href="https://tei-c.org/release/doc/tei-p5-doc/en/html/TD.html#TDPMPM">TEI Guidelines</link> provide a list of suggested behaviours. TEI Publisher allows users to add their own custom behaviours, either within the ODD itself or by writing XQuery code.</para>
   <para>Behaviours define what kind of transformation is expected for the given input. In this sense, behaviours are functions and they may accept a range of parameters, depending on the function in question. For example, the <code>link</code> behaviour needs at least two parameters specifying how the URL for the link should be constructed and what the visible link text should be. </para>
   <note><para>Behaviours, as abstract concepts, remain media agnostic. Their implementations in the TEI Processing Model library handle the mapping of the concept to the concrete output format, e.g. HTML or print. <code>inline</code> or <code>note</code> behaviours hardly differ across media, but obviously we cannot have hyperlinks on printed page, therefore <code>link</code> behaviour needs to be adjusted for print outputs.</para></note>
   <para>Even with <code>behaviour</code>s, we still lack a way to describe the required formatting for our model, for example to declare that phrases marked as deleted should be rendered with a strike-through, titles should be italicized and lacunae marked with <code>[...]</code>. The CSS standard is extremely well suited to express such editorial decisions, therefore TEI Guideline specification highly recommends using CSS definitions for this purpose and TEI Publisher strictly <emphasis>requires</emphasis> it. Follow to <link linkend="model-styling">output styling</link> section for details.</para>
   <note><para>Please note that any electronic publication needs a general CSS design, regarding layout and styling of its user interface components. Such concerns should be separated as much as possible from the specifications of the processing models. TEI Publisher provides recommendations how to handle these aspects in <link linkend="css-styling">custom CSS styling</link> chapter.</para></note>
   <para>Illustration below shows, how the same <code>inline behaviour</code> can be used to process elements that are semantically very different. Just by adjusting the <code>content</code> parameter and specifying the required rendition in CSS the editorial intention for processing can be easily and clearly expressed.</para>
   <note><para>CSS specification for each <code>model</code> can be provided directly, via nested <code>outputRendition</code>, or, better, indirectly, setting the <code>cssClass</code> on the <code>model</code> and placing actual CSS rules in a separate file.</para></note>
   
        <figure>
          <title>Examples of inline behaviour</title>
          <mediaobject>
            <imageobject>
              <imagedata fileref="pm-inline.jpg"/>
            </imageobject>
          </mediaobject>
        </figure>
      </section>
   <section xml:id="pm-contexts">
    <title>Context-differentiated models</title>
   
   <para>As mentioned above, processing models are defined first and foremost at the level of an individual markup element (XML tag). 
   Requirements for the transformation are often relatively simple, for example, virtually all TEI-based editions will render <code>p</code> elements as paragraphs and <code>foreign</code> phrases as inline elements. <code>unclear</code> will be often followed by a <code>(?)</code> and <code>sic</code> by <code>(!)</code>. For substantial majority of TEI, DocBook and JATS elements a single model suffices to process it.</para>
   
   <para>On the other hand, a much smaller, but significant, number, particularly for TEI tags, require variant handling. It may be depending on the project conventions, the context in which the element appears in the source XML structure, and also the application context it is presented in. Let's illustrate these three situations with examples.</para>
   
   <variablelist>
    <varlistentry>
      <term>Community convention</term>
      <listitem>
        <para>Words or phrases supplied by the editor where they are illegible or erroneously omitted in the source are encoded in TEI by <code>supplied</code> tag. Typical rendition of this phenomenon uses square brackets <code>[]</code> to mark the supplied phrase, while the dominant convention in Polish textual scholarship calls for angle brackets <code>&lt;&gt;</code>. Similar differences can be observed in typesetting conventions for expansion of abbreviations, marking of lacunae etc.</para>
      </listitem>
    </varlistentry>
    <varlistentry>
      <term>XML context</term>
      <listitem>
        <para>TEI element <code>title</code> may be used in various locations in the TEI file. It is often used in the transcription, where any kind of work might have been mentioned in the source text. <code>title</code> may also occur in various metadata sections, from bibliography to the title of the TEI file itself. Depending on the context, it will be presented differently: the title of the entire TEI document will often be rendered as top-level heading, while one of the titles mentioned in the transcribed documents will typically become just an italicized inline phrase.</para>
      </listitem>
    </varlistentry>
    <varlistentry>
      <term>Application context</term>
      <listitem>
        <para>The same source fragment may require different handling depending what is the purpose of the presentation. Let's assume that in our source document we have heavily encoded section heading (<code>head</code>), which includes a reference to a person (<code>persName</code>), but due to the damage to the manuscript witness, it is not fully legible. Nevertheless, the name can be easily reconstructed (<code>supplied</code>) based on other evidence available to the editor, who duly provides an explanatory note about the reconstruction process (<code>note</code>).</para>
        <para>In the reading view of the edition, we want all the encoded information available to the reader, with the conjecture marked with brackets according to the convention, editorial note signaled with a note anchor in superscript and provided as a footnote, and possibly additional information about the identification of the person accessible as a tooltip or margin note.</para>
        <para>On the other hand, for the table of contents, all the above would be just an irritating distraction, and in this scenario we want simply the plain, reading content of the heading.</para>
      </listitem>
    </varlistentry>
   </variablelist>
   
   <para>Illustration below depicts a case where requirements for the <emphasis>reading</emphasis> view are drastically different from the <emphasis>table of content</emphasis>: the former including extensive critical apparatus and commentary, as well as some information about the layout of the primary source, while table of content focuses on chapter number with supplementary information regarding the range of paragraphs belonging to it. Chapter heading in this case is only available as a tooltip and rendered without any scholarly apparatus.</para>
        <figure>
          <title>Processing requirements differing in various application contexts</title>
          <mediaobject>
            <imageobject>
              <imagedata fileref="pm-c7s.jpg"/>
            </imageobject>
          </mediaobject>
        </figure>
    <note><para>Example above originates from the <link xlink:href="https://www.unige.ch/c7s/">Canoniser les Sept Sages</link> project.</para></note>
      </section>
    </section>

    <section xml:id="pm-syntax">
      <title>Processing Model Syntax</title>
      <para>TEI Guidelines introduced a small number of new elements for the TEI Processing Model: <code>model</code>, <code>modelSequence</code>, <code>modelGrp</code>, <code>param</code> and <code>outputRendition</code>. It also extended the content model of <code>elementSpec</code> to allow to nest processing models in it. 
      In practice, we need just the small number of elements below to fully express intended transformation for any XML document:</para>
      <variablelist>
        <varlistentry>
          <term><code>model</code></term>
          <listitem>
            <para>describes the processing intended for a specified element</para>
          </listitem>
        </varlistentry>
        <varlistentry>
          <term><code>param</code></term>
          <listitem>
            <para>provides a parameter for a model behaviour by supplying its name and value</para>
          </listitem>
        </varlistentry>
        <varlistentry>
          <term><code>modelSequence</code></term>
          <listitem>
            <para>any sequence of <code>model</code> or nested <code>modelSequence</code> elements which is to be processed as a sequence, not mutually exclusive alternatives</para>
          </listitem>
        </varlistentry>
        <varlistentry>
          <term><code>outputRendition</code></term>
          <listitem>
            <para>describes the intended appearance for the model behaviour's output</para>
          </listitem>
        </varlistentry>
        <varlistentry>
          <term><code>pb:template</code>*</term>
          <listitem>
            <para>code template replacing the default <code>content</code> parameter accepted by all behaviours</para>
          </listitem>
        </varlistentry>
        <varlistentry>
          <term><code>pb:behaviour</code>*</term>
          <listitem>
            <para>custom behaviour definition</para>
          </listitem>
        </varlistentry>
      </variablelist>
        <note><para>Asterisks (*) mark TEI Publisher extensions to the TEI Processing Model syntax. These elements are therefore not in the TEI namespace, but the TEI Publisher namespace, denoted with the <code>pb:</code> prefix.</para></note>
        
      <section xml:id="pm-syntax-model">
        <title><tag>model</tag> element</title>
        <para>
          <tag>model</tag> element is primarily used to document the intended processing for a given
          element. One or more of these elements may appear directly within an
            <tag>elementSpec</tag> element specification to define the processing anticipated for
          that element. Where multiple <tag>model</tag> elements appear, they are understood to
          document mutually exclusive processing scenarios, possibly for different outputs or
          applicable in <link linkend="pm-contexts">different contexts</link>. </para>
        <para>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 <emphasis role="bold">behaviours</emphasis> and their parameters, using high-level formatting
          concepts, such as <parameter>block</parameter>, <parameter>inline</parameter>, <parameter>
            note</parameter> or <parameter>heading</parameter>. 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. </para>
        <para> The example below depicts a situation where a single model is defined for the
            <tag>app</tag> element. As no <parameter>@predicate</parameter> or
            <parameter>@output</parameter> are specified, this model applies for all contexts in
          which <tag>app</tag> may appear and all possible outputs. Thus all <tag>app</tag> elements
          will be transformed into inline chunks of text containing only contents of <tag>app</tag>
          's <tag>lem</tag> child and omitting any possible <tag>rdg</tag> children. </para>
        <programlisting language="xml" xml:space="preserve">&lt;elementSpec mode="change" ident="app"&gt;
  &lt;model behaviour="inline"&gt;
    &lt;param name="content" value="lem"/&gt;
  &lt;/model&gt;
&lt;/elementSpec&gt;</programlisting>
  <note>
    <para>Processing model for <code>app</code> presented above would be most likely insufficient for a scholarly publication. For practical examples consult the TEI Publisher ODD and custom ODD files available in TEI Publisher Documentation &amp; Demo.</para>
  </note>
</section>
        <section xml:id="pm-syntax-model-children">
          <title>
            <tag>model</tag> children and attributes</title>
          <para>
            <itemizedlist>
              <listitem>
                <para>
                  <parameter>@predicate</parameter> : the condition under which this model applies,
                  given as an XPath Predicate Expression </para>
              </listitem>
              <listitem>
                <para>
                  <parameter>@behaviour</parameter> : 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 </para>
              </listitem>
              <listitem>
                <para>
                  <parameter>@cssClass</parameter> : one or more CSS class names which should be
                  added to the resulting output element where applicable </para>
              </listitem>
              <listitem>
                <para>
                  <parameter>@output</parameter> : identifier of the output for which this
                  model applies; applies to all output if no @output is present on a
                    <tag>model</tag>
                </para>
              </listitem>
              <listitem>
                <para>
                  <parameter>@useSourceRendition</parameter> : whether to obey any rendition
                  attribute which is present in the source document</para>
              </listitem>
              <listitem>
                  <para><parameter>@pb:mode</parameter> : <link linkend="pm-mode">processing mode</link> to set to any subsequently called models</para>
              </listitem>
              <listitem>
                <para>
                  <tag>param</tag> : 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 </para>
              </listitem>
              <listitem>
                <para>
                  <tag>outputRendition</tag> : 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 </para>
                  <note><para>NB: this element should be used with care, it is <emphasis role="bold">strongly recommended to use <code>@cssClass</code></emphasis> wherever possible</para></note>
              </listitem>
            </itemizedlist>
          </para>
          </section>
          
        <section xml:id="model-styling">
          <title><tag>model</tag> output styling</title>
          <para>The intended rendering for the output of a processing model may be
            controlled in one of the following ways.</para>
          <itemizedlist>
            <listitem>
              <para><code>model</code>'s <code>@cssClass</code> attribute may be used to specify the name
                of a CSS style class in an associated CSS stylesheet (read more on <link linkend="css-styling-external">specifying CSS styles in the ODD</link>) which is to be
                applied,</para>
            </listitem>
            <listitem>
              <para>the attribute <parameter>@useSourceRendition</parameter> may be used to
                indicate that the rendition defined in the source document should be applied (applicable only to TEI documents using pointers to <link xlink:href="https://tei-c.org/release/doc/tei-p5-doc/en/html/ref-rendition.html">CSS rendition schemes</link>),
              </para>
            </listitem>
            <listitem>
                <para>CSS definition for the default model CSS class (<code>tei-{ident}</code>) may be provided</para>
            </listitem>
            <listitem>
              <para> 
                  <tag>outputRendition</tag> element, specifying the styling to be applied in CSS. This option should be used with care, 
                  it is strongly recommended to use <code>@cssClass</code> wherever possible to separate concerns and avoid redundancy.</para>
            </listitem>
          </itemizedlist>
          <note><para> It is strongly recommended that use <tag>outputRendition</tag> is strictly limited to
         editorial decisions, such as '<emphasis>conjectures are to be displayed in
              square brackets</emphasis>' or avoided altogether. Under no circumstances it should be used as means to record general typesetting and layout
            specific design choices. The latter are discussed in the <link linkend="css-styling">Custom CSS styling</link> chapter. </para></note>
         
          <para> 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. </para>
            
            <para>All TEI Processing Model behaviours (except <option>omit</option> and
          <option>pass-through</option>) add two CSS classes to the generated HTML element: one consisting of
        the name of the element preceded by the vocabulary prefix (e.g. <code>tei-div</code>) and the other additionally suffixed with the number of the model that has been applied (e.g. <code>tei-div2</code>). The former allows to specify CSS rules for all the elements belonging to this class. TEI Publisher provides the <code>tp.css</code> CSS stylesheet accompanying the default <code>teipublisher.odd</code>, with definitions for some of the default CSS classes, for example to ensure default italicization of <code>hi</code> elements or titles.</para>
        
        <para>Link to an external CSS stylesheet can be defined in the
          <code>encodingDesc/tagsDecl/rendition</code> section of the ODD. Just specify a relative
        link in the <parameter>@source</parameter> attribute, e.g.: </para>
      <programlisting language="xml" xml:space="preserve">
                  &lt;rendition source="docbook.css"/&gt;
          </programlisting>
      <para>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.</para>
        
        <para>When necessary, the processing model library translates the CSS styles into the target media
            format, e.g. for LaTeX. Restrictions apply due to differences between the output formats. Not all CSS
            properties are supported for every format. Please refer to the section on <link linkend="output-media">Output media settings</link> for further information. </para>
            
          
           
      <para>As an alternative to linked CSS files, the <tag>rendition</tag> element can be used with the
          <parameter>@selector</parameter> attribute to embed CSS rules directly in the ODD.</para>

      <programlisting language="xml" xml:space="preserve">&lt;rendition selector="h3"&gt;
  font-family: serif;
  font-weight: 400;
&lt;/rendition&gt;</programlisting>
      <para>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!</para>

        </section>
     <section xml:id="pm-model-styling-examples">
          <title>output styling example</title>
          
<para> Model specifying desired rendition via <code>cssClass</code>: contents of <tag>ex</tag> elements are to be
            displayed in italic and wrapped in parentheses: </para>
          <programlisting language="xml" xml:space="preserve">&lt;elementSpec mode="change" ident="ex"&gt;
  &lt;model behaviour="inline" cssClass="ex"/&gt;
&lt;/elementSpec&gt;</programlisting>

<para>The ODD file must declare a corresponding CSS stylesheet in <code>rendition</code> element in the <code>encodingDesc</code> section of the <code>teiHeader</code>. In the example below, a file called <code>tp.css</code> is expected to contain definitions for CSS classes used in the ODD processing models.</para>

<programlisting language="xml" xml:space="preserve">
&lt;TEI&gt;
    &lt;teiHeader&gt;
        ...
            &lt;encodingDesc&gt;
            &lt;tagsDecl&gt;
                &lt;rendition source="tp.css"/&gt;
            &lt;/tagsDecl&gt;
        &lt;/encodingDesc&gt;
    &lt;/teiHeader&gt;
    ...
&lt;/TEI&gt;
</programlisting>

<para>CSS definitions in the <code>tp.css</code> file declared in the ODD example above could be formulated as follows: </para>

<programlisting language="css" xml:space="preserve">
.ex {
    font-style: italic;
}

.ex::before {
    content: '(';
}

.ex::after {                   
    content: ')';
}
</programlisting>
          <para>Alternative rendering specification using <code>outputRendition</code> is presented below. This method is not recommended, as it leads to verbose and redundant CSS definitions inlined in the ODD. It tends to bloat the ODD and makes it harder to maintain for complex projects, mixing up presentational and functional concerns.</para>
          <programlisting language="xml" xml:space="preserve">&lt;elementSpec mode="change" ident="ex"&gt;
  &lt;model behaviour="inline"&gt;
    &lt;outputRendition&gt;font-style: italic;&lt;/outputRendition&gt;
    &lt;outputRendition scope="before"&gt;content:"(";&lt;/outputRendition&gt;
    &lt;outputRendition scope="after"&gt;content:")";&lt;/outputRendition&gt;
  &lt;/model&gt;
&lt;/elementSpec&gt;</programlisting>
</section>
<section xml:id="pm-model-multiple">
<title>multiple <code>model</code>s</title>
          <para>As discussed in an <link linkend="pm-contexts">earlier section</link>, sometimes several processing models are required for the same element depending on the context. 
            </para>
            <para>Set of
            multiple <tag>model</tag> statements is regarded as <emphasis role="bold">mutually exclusive alternation</emphasis> and <emphasis role="bold">only the first</emphasis>
            model with <parameter>@predicate</parameter> <emphasis role="bold">matching</emphasis> the current context <emphasis role="bold">is applied</emphasis>.</para>
            <para>
                    <code>model</code> and <code>modelSequence</code> elements are evaluated <emphasis role="bold">top to bottom</emphasis>, in the TEI ODD document order. The first one for which the <code>@predicate</code> condition is satisfied will be applied. Further processing models will not be evaluated at all.</para>
            <para>
                    <code>@predicate</code> can be specified as any XPath expression which will be evaluated to logically <emphasis>true</emphasis> or <emphasis>false</emphasis>. Typically behaviour predicates test one or more of the following characteristics:</para>
            <variablelist>
              <varlistentry>
                <term>the presence or a specific value of element's attribute</term>
                <listitem>
                  <para>
                    <code>predicate="@target"</code> : true if current element has a <code>target</code> attribute</para>
                  <para>
                    <code>predicate="@type='chapter'"</code> : true if current element has a <code>type</code> attribute and its value is specifically <emphasis>chapter</emphasis>
                  </para>
                </listitem>
              </varlistentry>
              <varlistentry>
                <term>presence of a child or further descendant</term>
                <listitem>
                  <para>
                    <code>predicate="lem"</code> : true if current element has a <code>lem</code> child element</para>
                  <para>
                    <code>predicate="descendant::pb"</code> : true if current element has a page beginning nested anywhere down the XML tree hierarchy</para>
                </listitem>
              </varlistentry>
              <varlistentry>
                <term>presence of a specific parent or ancestor</term>
                <listitem>
                  <para>
                    <code>predicate="ancestor::table"</code> : true if current element is somewhere within a table</para>
                  <para>
                    <code>predicate="parent::div"</code> : true if current element is a direct child of a division</para>
                  <para>
                    <code>predicate="parent::div[@type='chapter']"</code> : true if current element is a direct child of a <emphasis>chapter</emphasis> level division</para>
                </listitem>
              </varlistentry>
              <varlistentry>
                <term>value of an external parameter passed from the outside*</term>
                <listitem>
                  <para>
                    <code>$parameters?mode=('toc', 'breadcrumb')</code> : true if the external parameter called <code>mode</code> is set to <emphasis>toc</emphasis> or <emphasis>breadcrumb</emphasis>
                  </para>
                  <note>
                    <para>* Convention for referring to, and evaluating, external parameters, is dependant on the processing model engine. <productname>TEI Processing Model library</productname>, used in TEI Publisher, employs the XPath syntax and passes external parameters via <code>$parameters</code> map structure.</para>
                  </note>
                </listitem>
              </varlistentry>
            </variablelist>
            <para>Predicate tests may use logical operators of conjunction (<code>and</code>) or alternative (<code>or</code>) to create more complex expressions, following the rules of <link xlink:href="https://www.w3.org/TR/xpath-31/">XPath expression language</link>.</para>
        </section>
            <section xml:id="pm-model-multiple-example">
<title>matching <code>model</code>s example</title>
            <para>For a simple case where single model is insufficient, let's focus on quotes. We may wish to process the <tag>quote</tag> element as
            an inline italic phrase when it appears inside a paragraph (<tag>p</tag> element), but as an
            indented block when it appears elsewhere. To achieve this, we need to change the
            specification for the <tag>quote</tag> element to include two <tag>model</tag> elements
            as follows: </para>
          <programlisting language="xml" xml:space="preserve">&lt;elementSpec mode="change" ident="quote"&gt;
  &lt;model predicate="ancestor::p" behaviour="inline"/&gt;
  &lt;model behaviour="block"/&gt;
&lt;/elementSpec&gt;</programlisting>
          <para> The first processing model will be matched and used only for <tag>quote</tag> elements which
            match the XPath expression given as the value of the <parameter>@predicate</parameter>
            attribute. Other element occurrences will use the second processing model. 
          </para>
          <note>
            <para>Given that quotes are ubiquitous in TEI and may occur in a number of contexts, a more appropriate predicate could test for other contexts than paragraph ancestor, as it happens in the <link xlink:href="https://github.com/eeditiones/jinks/blob/b6523a09fbbdee6c5141a2d762ff52f11fc27be2/profiles/base10/resources/odd/teipublisher.odd#L616">TEI Publisher ODD</link>.</para>
          </note>
      </section>
      <section xml:id="pm-syntax-modelSequence">
        <title>
          <tag>modelSequence</tag>
        </title>
        <para>The <tag>modelSequence</tag> element is
          provided for the case where a sequence of models is to be processed, functioning as a
          single unit.</para>
        <para>As discussed earlier, when multiple <code>model</code> elements occur as direct children of the <code>elementSpec</code>, they are treated as mutually exclusive and only one of the models will be applied during the transformation.</para>
        <para>Nevertheless, sometimes it is necessary to apply two or more behaviour functions to the same source element. Let's consider a verse line, where apart from the content of the line we may want the verse number presented to the side (typically not for each verse, but for every fifth or so).</para>
        <para>To achieve this effect, we might want to apply two models in a sequence: first one using the <code>n</code> attribute as the <code>parameter</code> to produce the ordinal, and a second one, to transform the actual content of the line.</para>
              <para>
          <code>modelSequence</code> element is a wrapper that can be used around any group of nested <code>model</code> (and <code>modelSequence</code>) elements, to ensure that they are all applied. Models are evaluated (checking if predicate tests are satisfied in the current context), and applied in the sequence determined by the ODD document order.</para>
              <para>
        Please note that since predicate rules still apply, therefore in the example below, the first model in the sequence will only be applied for every 5th verse.</para>
        
         <programlisting language="xml" xml:space="preserve">&lt;elementSpec mode="change" ident="l"&gt;
    &lt;modelSequence&gt;
      &lt;model predicate="(number(@n) mod 5) = 0" behaviour="inline"&gt;
         &lt;param name="content" value="@n"/&gt;
      &lt;/model&gt;
      &lt;model behaviour="block"/&gt;
    &lt;modelSequence&gt;
&lt;/elementSpec&gt;</programlisting>

<note>
              <para>
                        <code>modelSequence</code> is not the only way to achieve similar effect, depending on the precise requirements, alternative approaches would modify the <code>content</code> parameter, or use <code>pb:template</code> extension. Particularly to produce nested markup structures the latter method is most useful.</para>
                </note>
        <figure>
          <title>Numbered verse lines example from <link xlink:href="https://neolatina.dhlab.uj.edu.pl/exist/apps/neolatina/s48-1">Neolatina Sarmatica</link>.</title>
          <mediaobject>
            <imageobject>
              <imagedata fileref="pm-verse.jpg"/>
            </imageobject>
          </mediaobject>
    </figure>
   
        <para>Another use case would be to use modelSequence to generate table of contents
          preceding the reading text as shown in the example below: </para>
        <programlisting language="xml" xml:space="preserve">&lt;elementSpec mode="change" ident="body"&gt;
  &lt;modelSequence&gt;
    &lt;model behaviour="index"&gt;
      &lt;param name="type" value="'toc'"/&gt;
    &lt;/model&gt;
    &lt;model behaviour="block"/&gt;
  &lt;/modelSequence&gt;
&lt;/elementSpec&gt;</programlisting>
      </section>
        <section xml:id="pm-syntax-modelGrp">
        <title>
                <tag>modelGrp</tag> (processing model group) </title>
        <para> The <tag>modelGrp</tag> element may be used to group <tag>model</tag>s for better readability of the code, for example
          elements intended for the same output format.</para>
          <note>
                    <para>This element, though present in the specification, has little use in practice and we <link xlink:href="https://github.com/TEIC/TEI/issues/2856">do not recommend</link> its use.</para>
                </note>
      </section>
    </section>
    <section xml:id="behaviours">
        <title>Behaviours</title>
        <para> The <link xlink:show="new" xlink:href="http://www.tei-c.org/release/doc/tei-p5-doc/en/html/ref-model.html">TEI
            Guidelines</link> list a number of suggested behaviours. TEI Publisher implements all these, supplemented with a few <emphasis>additional</emphasis> ones. Users may also add their own custom behaviours, either within the ODD itself, or by implementing custom behaviours in <link linkend="extension-modules">XQuery</link>. </para>
        <para>Illustration below shows relative frequency of use of behaviours in the TEI Publisher ODD. <code>inline</code> and <code>block</code> behaviours are used in more than 50% of models. Close to 10% of models uses <code>pass-through</code> behaviour which in majority of cases corresponds with the use of <link linkend="pb-template"><code>pb:template</code> extension</link>.</para>
        <para>Several other behaviours are used relatively frequently: <code>alternate</code>, <code>link</code>, <code>heading</code>, <code>list</code> and <code>listItem</code> as well as <code>omit</code>, <code>webcomponent</code>, <code>paragraph</code> and <code>break</code>.</para>
        <para>Other behaviours are very closely tied to the specific elements they tend to be solely used for, e.g. <code>table</code> and related <code>row</code> and <code>cell</code> behaviours are used exclusively by their eponymous elements in TEI (and by <code>table</code>, <code>tr</code>, <code>td</code> and 
        <code>th</code> elements in DocBook, respectively).</para>
        <para>What follows, in ODD customization practice, we'll typically need to use just a handful of most frequent behaviours, therefore it pays off to familiarize yourself with these first.</para>
            <figure>
          <title>Behaviour distribution in TEI Publisher ODD</title>
          <mediaobject>
            <imageobject>
              <imagedata fileref="behaviour-distribution.jpg"/>
            </imageobject>
          </mediaobject>
    </figure>
        <section xml:id="behaviours-available">
          <title>Standard behaviours</title>
          <para>This section lists the behaviours supported by TEI Processing Model library out of the box. 
          These include all behaviours suggested by the TEI Guidelines and several additional ones, commonly used in TEI Publisher-based editorial projects.
          </para>
          <para> Behaviour functions accept a range of parameters, depending on the function in
            question. Where these parameters are not explicitly specified in the <tag>model</tag>, default
            values are used.</para>
          <para>All behaviour functions have at least one parameter called 
              <parameter>content</parameter> (with a slight exception of <code>alternate</code> behaviour, where equivalent parameter is called <parameter>default</parameter>). By default the <code>content</code> is set to XPath expression <code>.</code>, which means
              the currently processed node. You may adjust this by
            explicitly changing the <parameter>content</parameter> parameter value in the <code>model</code>. </para>
          <para> In the parameter lists below we skip the <parameter>content</parameter> parameter
            as it is available for every behaviour. Optional parameters are marked as <emphasis>
              optional</emphasis> in parentheses, followed by the output mode they apply to, if
            relevant. </para>
          <variablelist>
            <varlistentry>
              <term>alternate</term>
              <listitem>
                <para>Present <emphasis>default</emphasis> and <emphasis>alternative</emphasis> content. The
                  concrete implementation depends on the output format. Typical web-oriented implementation relies on using a dynamic tooltip to display the alternate content.</para>
                <informaltable>
                  <thead>
                    <tr>
                      <td>Parameter</td>
                      <td>Description</td>
                    </tr>
                  </thead>
                  <tbody>
                    <tr>
                      <td>default</td>
                      <td>the content to display by default</td>
                    </tr>
                    <tr>
                      <td>alternate</td>
                      <td>alternate content</td>
                    </tr>
                    <tr>
                      <td>persistent</td>
                      <td>(optional, web) show a persistent popup on click instead of a tooltip on
                        hover if parameter evaluates to an effective boolean value of true</td>
                    </tr>
                  </tbody>
                </informaltable>
              </listitem>
            </varlistentry>
            <varlistentry>
              <term>anchor</term>
              <listitem>
                <para>Create an anchor to which you can link, identified by the given id.</para>
                <informaltable>
                  <thead>
                    <tr>
                      <td>Parameter</td>
                      <td>Description</td>
                    </tr>
                  </thead>
                  <tbody>
                    <tr>
                      <td>id</td>
                      <td>the id</td>
                    </tr>
                  </tbody>
                </informaltable>
              </listitem>
            </varlistentry>
            <varlistentry>
              <term>block</term>
              <listitem>
                <para>Create a block structure, usually a div in HTML or fo:block in fo.</para>
              </listitem>
            </varlistentry>
            <varlistentry>
              <term>body</term>
              <listitem>
                <para>Create the body of a document. In HTML this will result in a &lt;body&gt;
                  tag.</para>
              </listitem>
            </varlistentry>
            <varlistentry>
              <term>break</term>
              <listitem>
                <para>Create a line, column, or page break according to type.</para>
                <informaltable>
                  <thead>
                    <tr>
                      <td>Parameter</td>
                      <td>Description</td>
                    </tr>
                  </thead>
                  <tbody>
                    <tr>
                      <td>type</td>
                      <td>e.g. "page", "column", "line"</td>
                    </tr>
                    <tr>
                      <td>label</td>
                      <td>e.g. "p. 13v"</td>
                    </tr>
                  </tbody>
                </informaltable>
              </listitem>
            </varlistentry>
            <varlistentry>
              <term>cell</term>
              <listitem>
                <para>Create a table cell. If the @cols or @rows attribute is specified, the cell
                  may span several columns/rows.</para>
              </listitem>
            </varlistentry>
            <!-- MT: should we postulate deprecation of cit? it is unnecessarily specific, could be easily handled by block behaviour -->
            <varlistentry>
              <term>cit</term>
              <listitem>
                <para>Show a citation, with an indication of the source.</para>
                <informaltable>
                  <thead>
                    <tr>
                      <td>Parameter</td>
                      <td>Description</td>
                    </tr>
                  </thead>
                  <tbody>
                    <tr>
                      <td>source</td>
                      <td>the citation source</td>
                    </tr>
                  </tbody>
                </informaltable>
              </listitem>
            </varlistentry>
            <varlistentry>
              <term>document</term>
              <listitem>
                <para>Create output document wrapper. The
                  concrete implementation depends heavily on the output format. For example, in the case of LaTeX output this 
                  behaviour sets the document preamble, where options for the paper size, document layout, packages used and so on can be defined.</para>
              </listitem>
            </varlistentry>
            <varlistentry>
              <term>figure</term>
              <listitem>
                <para>Make a figure with provided title argument as caption.</para>
                <informaltable>
                  <thead>
                    <tr>
                      <td>Parameter</td>
                      <td>Description</td>
                    </tr>
                  </thead>
                  <tbody>
                    <tr>
                      <td>title</td>
                      <td>a caption</td>
                    </tr>
                  </tbody>
                </informaltable>
              </listitem>
            </varlistentry>
            <varlistentry>
              <term>graphic</term>
              <listitem>
                <para>Display the graphic retrieved from the given url.</para>
                <informaltable>
                  <thead>
                    <tr>
                      <td>Parameter</td>
                      <td>Description</td>
                    </tr>
                  </thead>
                  <tbody>
                    <tr>
                      <td>url</td>
                      <td>the url to load the graphic from</td>
                    </tr>
                    <tr>
                      <td>width</td>
                      <td>the width of the graphic, e.g. "300px", "50%" ...</td>
                    </tr>
                    <tr>
                      <td>height</td>
                      <td>the height of the graphic, e.g. "300px", "50%" ...</td>
                    </tr>
                    <tr>
                      <td>scale</td>
                      <td>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.</td>
                    </tr>
                    <tr>
                      <td>title</td>
                      <td>a title for the graphics element. Usually not shown directly.</td>
                    </tr>
                  </tbody>
                </informaltable>
              </listitem>
            </varlistentry>
            <varlistentry>
              <term>heading</term>
              <listitem>
                <para>Create a heading.</para>
                <informaltable>
                  <thead>
                    <tr>
                      <td>Parameter</td>
                      <td>Description</td>
                    </tr>
                  </thead>
                  <tbody>
                    <tr>
                      <td>level</td>
                      <td>the structural level of this heading. In HTML mode, this translates to
                        &lt;h1&gt;, &lt;h2&gt; etc.</td>
                    </tr>
                  </tbody>
                </informaltable>
              </listitem>
            </varlistentry>
            <varlistentry>
              <term>inline</term>
              <listitem>
                <para>Output an inline element.</para>
              </listitem>
            </varlistentry>
            <varlistentry>
              <term>link</term>
              <listitem>
                <para>Create a hyperlink.</para>
                <informaltable>
                  <thead>
                    <tr>
                      <td>Parameter</td>
                      <td>Description</td>
                    </tr>
                  </thead>
                  <tbody>
                    <tr>
                      <td>uri</td>
                      <td>the link url</td>
                    </tr>
                    <tr>
                      <td>target</td>
                      <td>identifier of the tab to open the link in (only web output)</td>
                    </tr>
                  </tbody>
                </informaltable>
              </listitem>
            </varlistentry>
            <varlistentry>
              <term>list</term>
              <listitem>
                <para> Create an ordered or unordered list, depending on the type attribute (e.g.
                    <parameter> type="ordered"</parameter>). If a label is present before each item,
                  a description list is output instead, using the label as definition term. </para>
                <informaltable>
                  <thead>
                    <tr>
                      <td>Parameter</td>
                      <td>Description</td>
                    </tr>
                  </thead>
                  <tbody>
                    <tr>
                      <td>type</td>
                      <td>The type of list: use "ordered" for an enumerated list, or "custom" to
                        specify item labels in combination with the <option>n</option> parameter on
                        each <command>listItem</command>. The default is "unordered" for a list of
                        bullet points. </td>
                    </tr>
                  </tbody>
                </informaltable>
              </listitem>
            </varlistentry>
            <varlistentry>
              <term>listItem</term>
              <listitem>
                <para>Output an item in a list.</para>
                <informaltable>
                  <thead>
                    <tr>
                      <td>Parameter</td>
                      <td>Description</td>
                    </tr>
                  </thead>
                  <tbody>
                    <tr>
                      <td>n</td>
                      <td>a label to use for the item</td>
                    </tr>
                  </tbody>
                </informaltable>
              </listitem>
            </varlistentry>
            <varlistentry>
              <term>metadata</term>
              <listitem>
                <para>Output a metadata section, e.g. a &lt;head&gt; in HTML.</para>
              </listitem>
            </varlistentry>
            <varlistentry>
              <term>note</term>
              <listitem>
                <para>create a note, often out of line, depending on the value of
                    <code>place</code> ; could be "margin", "footnote", "endnote", "inline" </para>
                <informaltable>
                  <thead>
                    <tr>
                      <td>Parameter</td>
                      <td>Description</td>
                    </tr>
                  </thead>
                  <tbody>
                    <tr>
                      <td>place</td>
                      <td>defines the placement of the note, e.g. "margin", "footnote" ...</td>
                    </tr>
                    <tr>
                      <td>label</td>
                      <td>the label to use for the footnote reference, usually a number.</td>
                    </tr>
                  </tbody>
                </informaltable>
              </listitem>
            </varlistentry>
            <varlistentry>
              <term>omit</term>
              <listitem>
                <para>Do nothing: skip this element, do not process children.</para>
              </listitem>
            </varlistentry>
            <varlistentry>
              <term>paragraph</term>
              <listitem>
                <para> Create a paragraph. </para>
              </listitem>
            </varlistentry>
            <varlistentry>
              <term>pass-through</term>
              <listitem>
                <para>Process the content without creating any kind of wrapper. Most often used together with <code>pb:template</code> to create more complex output markup or just with <code>content</code> parameter, to limit processing to selected content. The latter can be also used to specify arbitrary order for processing source fragments.</para>
              </listitem>
            </varlistentry>
            <varlistentry>
              <term>row</term>
              <listitem>
                <para> Create a table row. </para>
              </listitem>
            </varlistentry>
            <varlistentry>
              <term>section</term>
              <listitem>
                <para>Create a new section in the output document. In HTML mode, this translates to
                  a &lt;section&gt; element being output.</para>
              </listitem>
            </varlistentry>
            <varlistentry>
              <term>table</term>
              <listitem>
                <para>Create a table.</para>
              </listitem>
            </varlistentry>
            <varlistentry>
              <term>text</term>
              <listitem>
                <para>Output literal text.</para>
              </listitem>
            </varlistentry>
            <varlistentry>
              <term>title</term>
              <listitem>
                <para>Output the document title. In HTML mode, this creates a &lt;title&gt; element.
                  In LaTeX, it adds the title to the document metadata.</para>
              </listitem>
            </varlistentry>
            <varlistentry>
              <term>webcomponent (TEI Publisher extension)</term>
              <listitem>
                <para>Output a custom HTML element using the
                  value of parameter <parameter>name</parameter> as the custom tag name. All other parameters
                  are translated into corresponding attributes (properties of the webcomponent). </para>
                <informaltable>
                  <thead>
                    <tr>
                      <td>Parameter</td>
                      <td>Description</td>
                    </tr>
                  </thead>
                  <tbody>
                    <tr>
                      <td>name</td>
                      <td>the tag name to use for the custom element. Must be a string value.</td>
                    </tr>
                  </tbody>
                </informaltable>
              </listitem>
            </varlistentry>
          </variablelist>
        </section>
        <section xml:id="pb-behaviour">
          <title>Custom behaviours in the ODD</title>
          <para>The two dozen behaviours supported by TEI Processing Model library out of the box are enough to cover most
          standard tasks, but sometimes a custom behaviour may make the ODD code clearer and easier to maintain.</para>
          <para>By combining <link linkend="pb-template">code templates</link> with parameters we can create a very simple
            mechanism to define new behaviours right inside the ODD!</para>
          <para> 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 <tag>videodata</tag> elements inside a
              <tag>videoobject</tag>.</para>
          <programlisting xml:space="preserve">&lt;figure xml:id="edit-odd"&gt;
    &lt;title&gt;Screencast&lt;/title&gt;
    &lt;mediaobject&gt;
      &lt;videoobject&gt;
        &lt;videodata fileref="https://www.youtube.com/embed/avRO-b2BwUI?rel=0" width="853" depth="480"/&gt;
      &lt;/videoobject&gt;
    &lt;/mediaobject&gt;
&lt;/figure&gt;</programlisting>
          <para> In the HTML output we would need to transform this into an <tag>iframe</tag>, so
            the reader can view the video embedded in the page. We can achieve this with a <tag>
              pb:template</tag> 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 Processing Model library allows us to define a behaviour right inside the
            ODD as follows: </para>

          <programlisting xml:space="preserve">&lt;pb:behaviour ident="iframe" output="web"&gt;
    &lt;pb:param name="src"/&gt;
    &lt;pb:param name="width"/&gt;
    &lt;pb:param name="height"/&gt;
    &lt;pb:template xmlns=""&gt;
        &lt;iframe src="[[src]]" width="[[width]]" height="[[height]]" frameborder="0" gesture="media" allow="encrypted-media" allowfullscreen="allowfullscreen"&gt;&lt;/iframe&gt;
    &lt;/pb:template&gt;
&lt;/pb:behaviour&gt;</programlisting>

          <note>
            <title>Note</title>
            <para>Note how we have to reset the namespace on the <tag>pb:template</tag>? 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 <code>iframe</code> would end up in the TEI
              namespace. Web browsers will usually ignore it, but it would be incorrect
              nevertheless.</para>
          </note>
          <para> All behaviours should be defined in the TEI header of the ODD file (or – to be exact – the <tag>
              tagsDecl</tag> part of the <tag>encodingDesc</tag>). You may create multiple behaviour
            declarations with the same <parameter>@ident</parameter>, provided that they apply to
            different <parameter>@output</parameter> modes. Parameters declared via
              <tag>pb:param</tag> without <parameter>@value</parameter> 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 <parameter>@value</parameter> attribute, the result of the
            XPath evaluation will be used as value for the parameter. </para>
          <para> The new behaviour defined above will be named <function>iframe</function> and takes three
            parameters: <parameter>src</parameter>, <parameter>width</parameter> and <parameter>
              height</parameter>. It can now be used by a <tag>model</tag> as follows: </para>
          <programlisting xml:space="preserve">&lt;model behaviour="iframe"&gt;
    &lt;param name="width" value="@width"/&gt;
    &lt;param name="height" value="@depth"/&gt;
    &lt;param name="src" value="@fileref"/&gt;
&lt;/model&gt;</programlisting>
          <para> For further code examples, please have a look at <link xlink:href="odd/docbook.odd" role="source">docbook.odd</link>, which is used for viewing the documentation. </para>
          <note>
            <title>Note</title>
            <para>The graphical ODD editor in TEI Publisher does not yet
              support defining your own behaviours via <tag>pb:behaviour</tag>. You have to make
              these changes in the source XML using an XML editor. You can,
              however, use the graphical editor to continue editing the ODD afterwards. It makes sure not to overwrite your hand-written code upon save. </para>
          </note>
        </section>
        <section xml:id="custom-behaviour-xquery">
        <title>Custom Behaviours in XQuery</title>
        
        <para>While TEI Publisher does provide ways to create custom behaviours in XQuery 
        this should only be used when well justified: custom
          XQuery behaviours limit the portability of the ODD and negatively influence maintenance. It is recommended 
          to rely on standard behaviours, <link linkend="pb-behaviour"><tag>pb:behaviour</tag></link> and <link linkend="pb-template"><tag>pb:template</tag></link>
          extensions of the ODD syntax wherever possible.</para>
          
          <para>Avoiding custom behaviours works quite well for HTML output, nevertheless edge cases exist where creating custom behaviours in XQuery makes sense. Follow instructions from the <link linkend="extension-modules">XQuery extension modules</link> chapter for this approach.</para>
          <para>
          
          Avoiding custom behaviours works quite well for HTML output and we have realized
          complex projects with no extension behaviours. Things may become more
          difficult for LaTeX output: 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 <tag>persName</tag>, experienced LaTeX users would
          normally create a corresponding <code>\persName</code> macro and handle the formatting
          details there. Similarly, processing highly specific XML sources, for example to produce the reference pages for the TEI Guidelines themselves, is best handled via custom XQuery behaviours.</para>
      </section>
    </section>
      
    <section xml:id="pb-template">
          <title>Custom markup templates with <tag>pb:template</tag>
          </title>
          <para>
          The standard supported behaviours are sufficient to cover most
          typical tasks, but more complex HTML markup or
          procedural output formats like LaTeX require more customization and control over the
          generated output. The TEI Publisher library therefore extends the processing model syntax with
          a custom element for defining code templates. The <code>pb:template</code> element belongs to TEI Publisher, not TEI namespace (
              <parameter> http://teipublisher.com/1.0</parameter>).</para>
          <para> Within the ODD, a <tag>model</tag> may define a <tag>pb:template</tag> element
            containing a code template. The template is expanded first, and the result is passed to
            the behaviour specified for the model, in place of the
              <parameter>content</parameter> parameter accepted by all behaviours. The very simple
            case of outputting a <tag>persName</tag> in LaTeX could therefore be written as: </para>

          <programlisting language="xml" xml:space="preserve">&lt;elementSpec ident="persName" mode="add"&gt;
    &lt;model behaviour="inline" output="latex"&gt;
        &lt;pb:template&gt;\persName{[[content]]}&lt;/pb:template&gt;
    &lt;/model&gt;
&lt;/elementSpec&gt;</programlisting>
          <para> The template can reference other parameters defined within the <tag>model</tag> by
            enclosing the parameter name in double brackets. In the example above we're referencing
            the default parameter <parameter>content</parameter>, which does not need to be explicitly
            specified. Here it therefore retains its default value, which in this situation is the content
            of the <tag>persName</tag> tag. The parameter will be processed in a normal way before it is passed into
            the template, so if <tag>persName</tag> contains any nested TEI markup, the matching
            processing models will be applied first.</para>
          <para>The result of expanding the template is then passed to the behaviour (
              <code>inline</code> in the example above).</para>
          <para> 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 <code>&lt;term ref="#termid"&gt;text&lt;/term&gt;</code>. In LaTeX this would
            translate to <code>\glslink{ref}{text}</code>, which can be easily produced by the
            following <tag>model</tag> : </para>
          <programlisting language="xml" xml:space="preserve">&lt;elementSpec ident="term" mode="add"&gt;
    &lt;model behaviour="inline" output="latex"&gt;
        &lt;param name="ref" value="substring-after(@ref, '#')"/&gt;
        &lt;pb:template&gt;\glslink{[[ref]]}{[[content]]}&lt;/pb:template&gt;
    &lt;/model&gt;
&lt;/elementSpec&gt;</programlisting>
          <para> We define an additional parameter <parameter>ref</parameter>, which contains the id
            string from the <parameter>@ref</parameter> attribute, stripping out the leading '#'. </para>
          <para>The templating mechanism is not limited to LaTeX, but may be used to generate
            HTML or FO markup, for example, if you have to generate a complex, nested HTML fragment for a
            single TEI element. This is difficult, and sometimes impossible, to achieve without
            templates.</para>
          <para>The following example uses the <parameter>pb-popover</parameter> webcomponent to
            display the <code>tei:persName</code> from a person register for a given <code>tei:persName/@key</code> of your
            TEI document. </para>
          <programlisting language="xml" xml:space="preserve">&lt;elementSpec ident="persName" mode="add"&gt;
        &lt;model behaviour="inline" cssClass="popover"&gt;
            &lt;param name="content" value="."/&gt;
            &lt;param name="key" value="@key"/&gt;
            &lt;param name="person-from-register" value="doc('/path/to/person.xml')//person[@id = @key]/persName[@type='full']/string()"&gt;
            &lt;pb:template xmlns="" xml:space="preserve"&gt;
                &lt;pb-popover data-ref="[[key]]"&gt;
                    &lt;span slot="default"&gt;[[content]]&lt;/span&gt;
                    &lt;span slot="alternate"&gt;[[person-from-register]]&lt;/span&gt;
                &lt;/pb-popover&gt;
            &lt;/pb:template&gt;
        &lt;/model&gt;
        </programlisting>
        </section>
    <section xml:id="extension-modules">
        <title>XQuery extension modules</title>
        <para> Where possible, developers should stick to the standard behaviours, or use the <link linkend="pb-behaviour"><tag>pb:behaviour</tag></link> and <link linkend="pb-template"><tag>pb:template</tag></link>
          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
          extension modules to be configured, with definitions of custom functions and behaviours which may be then used in the ODD.
          </para>
        
          <para> Configuration is done via an XML file which must reside in the same collection as
            the source ODD files. It contains a series of <tag>output</tag> elements, representing
            particular output modes (e.g. web or print) via <parameter>@mode</parameter> attribute.
              <tag> output</tag> element without a mode groups modules available for all output
            modes. </para>
          <para> Each <tag>output</tag> 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 <parameter>@odd</parameter> attribute. </para>
          <programlisting language="xml" xml:space="preserve">&lt;modules&gt;
    &lt;!-- functions or behaviours common to all output modes --&gt;
    &lt;output&gt;
      &lt;module uri="http://www.tei-c.org/tei-simple/xquery/common-functions" prefix="tc" at="xmldb:exist:///db/apps/my-app/modules/common.xql"/&gt;
    &lt;/output&gt;
    &lt;!-- General fo extension functions --&gt;
    &lt;output mode="print"&gt;
      &lt;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"/&gt;
    &lt;/output&gt;
    &lt;!-- Special web configuration for the documentation (to handle &lt;code&gt;) --&gt;
    &lt;output mode="web" odd="documentation"&gt;
      &lt;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"/&gt;
    &lt;/output&gt;
&lt;/modules&gt;</programlisting>
          <para> Whenever the library tries to locate a processing model function for a given
            behaviour, it will <emphasis role="bold">first</emphasis> check any extension module it
            knows to see if it contains a matching function. One can thus <emphasis role="bold">
              overwrite</emphasis> the default functions as well as define new ones. </para>
          <para> 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 these functions available to all output modes, just skip the
              <parameter>@mode</parameter> attribute. </para>
              
          
            <para>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.
                <filename>ext-html.xql</filename>) will be interpreted relative to the
                <filename>modules</filename> collection. </para>
          
        
        <section xml:id="extension-modules-behaviours">
          <title>Implementing Custom Functions and Behaviours</title>
          <para>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:</para>
          <variablelist>
            <varlistentry>
              <term>$config</term>
              <listitem>
                <para> a map containing configuration information as well as function references to
                  be called. The most important ones are <function>$config?apply($config,
                    $node)</function> and <function>$config?apply-children($config, $node,
                    $content)</function>. Both are function items and when called, continue
                  processing with either a single <parameter> $node</parameter> or a sequence of
                  nodes in <parameter>$content</parameter>. </para>
              </listitem>
            </varlistentry>
            <varlistentry>
              <term>$node</term>
              <listitem>
                <para>the TEI element being processed at the moment</para>
              </listitem>
            </varlistentry>
            <varlistentry>
              <term>$class</term>
              <listitem>
                <para> a list of HTML class names to be used. This includes automatically generated
                  class names as well as those passed via <parameter>@cssClass</parameter> on a
                  model item. </para>
              </listitem>
            </varlistentry>
            <varlistentry>
              <term>$content</term>
              <listitem>
                <para> because <parameter>content</parameter> is defined for every model rule, it is
                  always passed to a behaviour function (though it might be empty) </para>
              </listitem>
            </varlistentry>
          </variablelist>
          <para> For all additional parameters, the processing model implementation tries to fill
            each custom parameter with a corresponding value by looking through the <tag>param</tag>
            children of the <tag>model</tag> 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. </para>
          <para> For example, a custom behaviour called <code>code</code> for syntax highlighting in
            an extension module named <filename>ext-html.xql</filename> might look as follows: </para>
          <programlisting language="xquery" xml:space="preserve">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()?) {
    &lt;pre class="code {$class}" data-language="{if ($lang) then $lang else 'xquery'}"&gt;
    {replace(string-join($content/node()), "^\s+?(.*)\s+$", "$1")}
    &lt;/pre&gt;
};</programlisting>
          <para> It defines one function, <function>pmf:code</function>, which can be called from
            the ODD as follows, provided that the <filename>ext-html.xql</filename> module has been
            configured as described in the <link linkend="extension-modules">previous
              section</link>. </para>
          <programlisting language="xml" xml:space="preserve">
&lt;model behaviour="code"&gt; 
    &lt;param name="lang" value="@lang"/&gt; 
&lt;/model&gt;
        </programlisting>
        </section>
        <section xml:id="extension-modules-behaviour-parameters">
          <title>Custom Behaviours Accepting User-Defined Parameters</title>
          <para>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.</para>
          <para> To facilitate this, a behaviour function may declare a final parameter
              <code>$optional as map(*)</code>. If the processor finds <tag>param</tag> 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 <parameter>$optional</parameter> map.
          </para>
        </section>
      </section>
            <section xml:id="setting-parameters">
        <title>Setting ODD parameters</title>
        <para>There are several scenarios, where it's useful to pass a parameter to the ODD, or set it at some point in the processing, to be retrieved later: </para>
        <itemizedlist>
            <listitem><para>to access <link linkend="global-variables">global configuration parameters</link>, e.g. to determine the path to the registers or primary data collection to avoid redundance in hard-coding it in the ODD</para></listitem>
            <listitem><para><link linkend="external-parameters">external parameters</link>, informing the ODD processor about elements of the application context, e.g. user-selected language, or if we are in the table of content, breadcrumbs, register or perhaps a reading view</para></listitem>
          <listitem>
              <para>to influence processing of the subsequently called models for particular use case by setting a <link linkend="pm-mode">processing mode</link></para>
          </listitem>
          <listitem>
            <para>to <link linkend="pm-set-param">set a parameter</link> value in a processing model and have it available to all subsequently processed models to avoid repeated computation of a value, that can be re-used, e.g. expanding the facsimile prefix into reusable URL fragment</para>
          </listitem>
        </itemizedlist>

        <para>The last two scenarios have a lot in common, in fact setting a processing mode is a special case of setting an arbitrary parameter. 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 document fragment multiple times in the same processing context (usually
            the edition view).</para>
        <section xml:id="global-variables">
        <title>Global Configuration Variables</title>
        <para>Sometimes you may want to access global configuration parameters, e.g. to determine
          the data root collection of the current application.</para>
        <para>TEI Publisher imports some commonly needed elements of the global application configuration from the <code>odd-global.xqm</code> module.</para>
        <programlisting language="xml" xml:space="preserve">&lt;modules&gt;
    &lt;!-- Import global variables and functions from modules/odd-global.xqm --&gt;
    &lt;module uri="http://e-editiones.org/tei-publisher/odd-global" prefix="global" at="odd-global.xqm"/&gt;
    ...
&lt;/modules&gt;</programlisting>

<!--<note role="todo">-->
<!--                    <para>Discuss how to add custom global configuration elements</para>-->
<!--                </note>-->
      </section>
        <section xml:id="external-parameters">
          <title>External Parameters</title>
          <para> The script calling the processing model may pass external parameters into the ODD.
            They will be available in the variable <parameter>$parameters</parameter>, which is an
            XQuery map. Access parameters using <code>?</code>, the XQuery lookup operator. </para>
          <para>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":</para>
          <programlisting language="xml" xml:space="preserve">&lt;elementSpec mode="change" ident="fileDesc"&gt;
    &lt;model predicate="$parameters?header='short' behaviour="block" cssClass="header-short"&gt;
      &lt;param name="content" value="titleStmt"/&gt;
    &lt;/model&gt;
  ...
&lt;/elementSpec&gt;</programlisting>
          <para> The <tag>pb-view</tag> webcomponent also lets you define arbitrary parameters to be
            passed to the ODD via <tag>pb-param</tag>. For example, the breadcrumbs shown above this
            documentation page are realized by setting a parameter <parameter>mode</parameter> and
            can be queried in model predicates with
              <parameter>$parameters?mode='breadcrumbs'</parameter> . </para>
          <programlisting language="xml" xml:space="preserve">&lt;section class="breadcrumbs"&gt;
    &lt;pb-view id="title-view1" src="document1" subscribe="transcription"&gt;
        &lt;pb-param name="mode" value="breadcrumbs"/&gt;
    &lt;/pb-view&gt;
&lt;/section&gt;</programlisting>
          <para>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.</para>
          <para> A dedicated user interface webcomponent <link xlink:show="new" xlink:href="https://cdn.tei-publisher.com/api.html#pb-toggle-feature.0">
              <tag>pb-toggle-feature</tag>
            </link> exists for toggling between two values of a parameter. Example below would
            produce a checkbox which when on results in the value of <parameter>
              $parameters?mode</parameter> set to <parameter>diplomatic</parameter>, otherwise to
              <parameter> norm</parameter>. </para>
          <programlisting language="xml" xml:space="preserve">&lt;pb-toggle-feature name="mode" on="diplomatic" off="norm"&gt;Diplomatic View&lt;/pb-toggle-feature&gt;</programlisting>
        </section>
        <section xml:id="pm-mode">
          <title>Processing Modes </title>
          <para>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. 
            </para>
            <para>
            One example would be to render a person reference once in the running text, and again, as a
            footnote, but in that case enhanced with the associated commentary but stripped of any
            information regarding textual features such as scribal
            errrors in the spelling of the name, or gaps and stains on the parchment. </para>
            <para>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.</para>
            
          <para>TEI Publisher supports an extension attribute,
              <code>@pb:mode</code>, on a <code>model</code>. The value of the attribute will be
            taken as the name of the mode, and subsequently called models can test for it in a
              <code>predicate</code>
             in via special variable, <code>$mode</code></para>
             <para>For example, if you set <code>pb:mode</code> attribute to <code>register</code> on a model
             with
              <code>&lt;model behaviour="block" pb:mode="register"&gt;</code>, then subsequently called models (i.e. models for all 
              nodes nested within the current element) can be tested for the mode in a predicate, e.g. <code>&lt;model predicate="$mode='register'" .../&gt;</code>. </para>
              
               <para>None of the examples shipping with TEI Publisher needs this
          feature, but in some specific editions we do encounter situations which cannot be handled
          without them. Illustration below presents such a case, where in the edition text only one of the possible expansions is presented (<emphasis>Dat(ae)</emphasis>), but the apparatus below gives a rendition of all potential readings (<emphasis>Dat(ae) or Dat(um)</emphasis>). Both the edited text and the apparatus are generated from the same TEI fragment, but processed twice, under two models differentiated by mode, one resulting in an inline phrase, and the other in a footnote.</para>
           <figure>
          <title>Use case for applying different processing modes to the same TEI element <link xlink:href="http://dantiscus.al.uw.edu.pl/?f=letterSummary&amp;letter=116&amp;view=6#ftntid286509376">in Dantiscus' correspondence edition</link></title>
          <mediaobject>
            <imageobject>
              <imagedata fileref="dantiscus-processing-modes.jpg"/>
            </imageobject>
          </mediaobject>
    </figure>
        </section>

        <section xml:id="pm-set-param">
          <title>Setting parameters within the ODD</title>
          <para>A logical follow-up for setting the processing mode described in the previous
            section and <link linkend="external-parameters">passing external parameters</link>, 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. </para>
          <para>The syntax is almost the same as for the standard <code>param</code>, which would be set on the <code>model</code>. 
          Just the name of the element changes to
              <code>&lt;pb:set-param&gt;</code>, marking this as a special parameter which is
            <emphasis>"inherited"</emphasis> by subsequent models. </para>
          <para>Common motivation to use this feature would be for processing 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 the entire text or 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. </para>
            
          <para>Example below shows relevant ODD models for setting the <code>iiif</code> and <code>iiif-prefix</code> parameters on the <code>div</code> level, and later reusing these precomputed values to generate links to facsimile for every word. Due to data structure, reflecting the complex history of the manuscripts, scattered across archives and available from different IIIF services around the globe, the computation involves various lookups and benefits greatly from this optimization.</para>
            <figure>
          <title>Use case for pre-setting a parameter to optimize generation of IIIF links for every word, line and column in <link xlink:href="http://www.erabbinica.org/midrash/MekhY/transcription_MekhY_Ox24.xml?panels=0.1">eRabbinica</link></title>
          <mediaobject>
            <imageobject>
              <imagedata fileref="pm-erabbinica.jpg"/>
            </imageobject>
          </mediaobject>
    </figure>
            <programlisting language="xml" xml:space="preserve">
            &lt;elementSpec ident="div"&gt;
              &lt;model behaviour="block"&gt;
                &lt;pb:set-param name="iiif" value="
                    let $facs := (($parameters?root/ancestor::TEI)//pb[@facs])[1] 
                    let $prefix := substring-before($facs/@facs, ':') 
                    let $iiif := doc('/db/apps/erabbinica-data/data/sources/taxonomy/taxonomy.xml')/id($prefix)   
                    return $iiif//*:ptr/@target"/&gt;
                &lt;pb:set-param name="iiif-prefix" value="
                let $facs := (($parameters?root/ancestor::TEI)//pb[@facs])[1] 
                return substring-before($facs/@facs, ':')"/&gt;
                &lt;outputRendition xml:space="preserve"&gt;
                    direction: rtl;
                &lt;/outputRendition&gt;
              &lt;/model&gt;
            &lt;/elementSpec&gt;
          </programlisting>
          
          <programlisting language="xml" xml:space="preserve">
              &lt;elementSpec ident="w" mode="change"&gt;
                    &lt;model behaviour="inline"&gt;
                        &lt;param name="default" value="."/&gt;
                        &lt;param name="facs" value="
                            let $pattern := '^'||$parameters?iiif-prefix || ':' || '([^/]+).*$'   
                            return  
                                $parameters?iiif || replace(@facs, $pattern, '$1')"/&gt;
                        &lt;param name="coords" value="let $pattern := '^'||$parameters?iiif-prefix || ':' || '[^/]+/(.*)$'   return  ('[', replace(@facs, $pattern, '$1'), ']')"/&gt;
                        &lt;param name="ana" value="@ana"/&gt;
                            &lt;pb:template xmlns="" xml:space="preserve"&gt;&lt;span&gt;
                              &lt;pb-facs-link emit="transcription" facs="[[facs]]" coordinates="[[coords]]"&gt;[[default]]&lt;/pb-facs-link&gt;
                  			&lt;/span&gt;&lt;/pb:template&gt;
                    &lt;/model&gt;
                &lt;/elementSpec&gt;
          </programlisting>
        </section>

      </section>

      <section xml:id="pm-extensions-xquery">
        <title>XQuery or XPath</title>
        <para>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.</para>
        <para> 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 <code language="xquery">let $x := ...
            return ...</code> syntax. </para>
      </section>
      <section xml:id="pm-extensions-default">
        <title>Default Processing Model Rules</title>
        <para> It is possible to define a default <tag>elementSpec</tag> to be applied to all
          elements which are not already matched by another <tag>elementSpec</tag>'s model. TEI Processing Model default
          specifies that where no <tag>elementSpec</tag> is present for an element, processing descends down through child nodes, 
          as if <code>pass-through</code>behaviour was applied. To change this default and omit content elements 
          without specification, you may want to define a default <tag>elementSpec</tag> as shown below: </para>
        <programlisting language="xml" xml:space="preserve">
        &lt;elementSpec ident="*"&gt;
          &lt;model behaviour="omit"/&gt; 
        &lt;/elementSpec&gt;</programlisting>
        <para>You can also define models to match text nodes, e.g. if you need to
          normalize certain nodes:</para>
        <programlisting language="xml" xml:space="preserve">&lt;elementSpec ident="text()"&gt;
  &lt;model behaviour="text"/&gt;
&lt;/elementSpec&gt;</programlisting>
        <note><para>Note that outputting text nodes is a performance critical operation, so use with care.
          Complex processing may dramatically affect performance.</para></note>
      </section>
    <section xml:id="odd-chaining">
    <title>Chaining the ODDs</title>
        <para>In the spirit of reuse, it is considered best practice to chain the ODD files together and only change
      or add project specific rules to a custom ODD extending the base as necessary. Chaining allows for 
      future upgrades, as your base ODDs are updated by standardization bodies or communities maintaining them. 
      This way the custom ODD usually stays short and simple. TEI
      Publisher is shipping with an extensive base ODD (called <code>teipublisher.odd</code>) already supporting
      a wide range of use case scenarios. Custom ODDs would usually extend this ODD.</para>
    <para>While the base ODD provides a sensible rendition out of the box, concrete projects often
      require certain adjustments to fully meet its specific needs. It has been one of primary
      concerns in Publisher's design that customization is not only possible on all levels but
      actively encouraged and as simple as possible.</para>
    <para> Very broadly TEI PM customizations involve two aspects: adjusting the processing logic
      (how the source document is translated into the output format), and changing the styling and
      typesetting of the presented output. In this chapter we'll discuss both, as they primarily
      require modification of the ODD with the <link linkend="pm-syntax">TEI Processing
      Model</link>. As mentioned above, it is usually best to choose as your starting point an
      already existing ODD, e.g. teipublisher.odd and create a customization chained to it. </para>
    </section>
    
      <!--
      <para> 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 <tag>pb-view</tag> 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. <parameter>font-family</parameter>). </para>
        -->
    <section xml:id="output-media">
      <title>Output Specific Settings</title>
      <para> 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 <parameter>@output</parameter> attribute: </para>
      <variablelist>
        <varlistentry>
          <term>web</term>
          <listitem>
            <para>Produces HTML output</para>
          </listitem>
        </varlistentry>
        <varlistentry>
          <term>fo</term>
          <listitem>
            <para>Generates a PDF via XSL:FO</para>
          </listitem>
        </varlistentry>
        <varlistentry>
          <term>latex</term>
          <listitem>
            <para>Creates a PDF via LaTeX</para>
          </listitem>
        </varlistentry>
        <varlistentry>
          <term>print</term>
          <listitem>
            <para>Extends web output with a focus on Print and Paged Media (PrintCSS)</para>
          </listitem>
        </varlistentry>
        <varlistentry>
          <term>epub</term>
          <listitem>
            <para>A specialization of the web output mode targetted at epub documents</para>
          </listitem>
        </varlistentry>
        <varlistentry>
          <term>markdown</term>
          <listitem>
            <para>Plain text enhanced with markdown</para>
          </listitem>
        </varlistentry>
      </variablelist>
      <note>
        <para>By default, the base10 profile only enables the output modes <code>web</code>,
            <code>print</code> and <code>epub</code>. The <productname>markdown</productname>
          profile obviously adds <code>markdown</code> to the list. If you would like to use the
            <code>latex</code> or <code>fo</code> mode, you have to configure this in the
            <filename>config.json</filename>:</para>
        <programlisting language="json">{
  …
  "defaults": {
    "media": ["web", "print", "fo", "latex", "epub"]
  }
  …
}</programlisting>
      </note>
      <para>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:</para>
      <section xml:id="output-media-fo">
        <title>FO Output</title>
        <para>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.</para>
        <para>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.</para>
        <para> The library searches for default CSS styles in a file named <filename>
            &lt;odd-name&gt;.fo.css</filename> 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,
            <filename>teipublisher.fo.css</filename> contains: </para>
        <programlisting language="css" xml:space="preserve">
.tei-text { font-family: "Junicode"; hyphenate: true; }
.tei-floatingText { padding: 6pt; }
.tei-p { text-align: justify; }
        </programlisting>
        <para>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:</para>
        <variablelist>
          <varlistentry>
            <term>master.fo.xml</term>
            <listitem>
              <para>Contains the layout master set</para>
            </listitem>
          </varlistentry>
          <varlistentry>
            <term>page-sequence.fo.xml</term>
            <listitem>
              <para>Defines the main page sequence</para>
            </listitem>
          </varlistentry>
        </variablelist>
        <para>The mechanisms for configuring FO output are still very much under development and we
          welcome suggestions by users.</para>
      </section>
      <section xml:id="output-media-latex">
        <title>LaTeX Output</title>
        <para>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:</para>
        <itemizedlist>
          <listitem>
            <para>font-weight</para>
          </listitem>
          <listitem>
            <para>font-style</para>
          </listitem>
          <listitem>
            <para>font-variant</para>
          </listitem>
          <listitem>
            <para>font-size</para>
          </listitem>
          <listitem>
            <para>color</para>
          </listitem>
          <listitem>
            <para>text-decoration</para>
          </listitem>
          <listitem>
            <para>text-align</para>
          </listitem>
          <listitem>
            <para>text-indent</para>
          </listitem>
        </itemizedlist>
        <para> To create arbitary complex LaTeX output, you may want to use the <link linkend="pb-template">
            <tag>pb:template</tag> extension </link> to the ODD syntax. It is heavily used to e.g.
          generate the LaTeX version of this documentation. See also <link xlink:href="odd/serafin.odd" role="source">serafin.odd</link> or <link xlink:href="odd/vangogh.odd" role="source">vangogh.odd</link> for examples. </para>
        <para> 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 <tag>outputRendition</tag> which
          should be imported into the prolog. The styles are added to the default configuration map
          and can be accessed via <command>$config('latex-styles')</command>. Refer to the example
          ODDs and just copy/paste the corresponding lines. </para>
        <para> 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 <filename>modules/config.xqm</filename>. Search for the
          variable <parameter>$config:tex-command</parameter> and adjust it to point to a binary of
            <command> xelatex</command>, <command>pdflatex</command> or <command>lualatex</command>
          . </para>
      </section>
      <section xml:id="output-media-epub">
        <title>ePub Output</title>
        <para> The <parameter>epub</parameter> output mode extends the HTML mode. You may define
          general styling in an extra CSS file, located in
            <filename>resources/css/epub.css</filename>. 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. </para>
      </section>
      <section xml:id="output-print-css">
        <title>Print CSS</title>
        <para>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 <link xlink:href="https://pagedjs.org/">paged.js</link> to "<emphasis>teach</emphasis>" the browser how to handle certain
          layout aspects. Thanks to this, using the <command>print page</command> dialog of your
          browser will result in a much nicer page layout than if you just tried to print TEI
          Publisher's document view.</para>
        <para>You can find a more detailed discussion of the feature along with some CSS examples in
          this <link xlink:href="https://www.e-editiones.org/posts/print-css/">article on the
            e-editiones homepage</link>.</para>
        <para>The preview page uses TEI Publisher's <code>pb-print-preview</code> 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 <guibutton>eye</guibutton>
          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.</para>
        <para>To generate the HTML of the document, the component calls Publisher's API
          endpoint:</para>

        <synopsis>/api/document/doc%2Fdocumentation.xml/print</synopsis>
        <para>The following (optional) parameters are supported:</para>
        <variablelist>
          <varlistentry>
            <term>base</term>
            <listitem>
              <para>specifies the base URI for resolving relative links, e.g. to locate
                images</para>
            </listitem>
          </varlistentry>
          <varlistentry>
            <term>style</term>
            <listitem>
              <para>one or more additional CSS stylesheet URLs to be imported into the page.</para>
            </listitem>
          </varlistentry>
          <varlistentry>
            <term>script</term>
            <listitem>
              <para>one or more Javascript files to be loaded via <tag>script</tag>.</para>
            </listitem>
          </varlistentry>
          <varlistentry>
            <term>wc</term>
            <listitem>
              <para>if set, include TEI Publisher's web component libraries. You may need this if
                you are using components like <tag>pb-code-highlight</tag> (as in the
                documentation)</para>
            </listitem>
          </varlistentry>
        </variablelist>

        <para>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. <link xlink:href="https://www.princexml.com/">Prince XML</link>, <link xlink:href="https://www.pdfreactor.com/">PDF Reactor</link> or <link xlink:href="https://antennahouse.com/">Antennahouse</link>. A full list can be found on
            <link xlink:href="https://www.print-css.rocks/tools">print-css.rocks</link>. Each of
          those may have different strengths and weaknesses. Please try yourself.</para>

        <para>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:</para>

        <figure>
          <title> Processing Print HTML with PrinceXML </title>
          <mediaobject>
            <imageobject>
              <imagedata fileref="prince-screenshot.png"/>
            </imageobject>
          </mediaobject>
        </figure>
      </section>
    </section>
   
  </section>
  <section xml:id="anatomy">
    <title>Anatomy of a profile</title>
    <para>Everything in TEI Publisher 10 is a profile, which also includes any application you
      generate with jinks. Applications follow the same structure and hierarchical organization as
      other profiles. The difference is only that an application includes the merged content of all
      the profiles it extends. When you update an application, changes contributed by the various
      dependant profiles will be injected into the correct place within the collection hierarchy. To
      customize an application, it is therefore helpful to know the basic anatomy. It is also vital
      to respect the naming scheme where one is documented to avoid conflicts and guarantee smooth
      updates.</para>
    <para>The most important locations inside the application hierarchy are:</para>
    <variablelist>
      <varlistentry>
        <term>config.json</term>
        <listitem>
          <para>Contains the configuration for the profile or application and declares its
            dependencies on other profiles</para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>.jinks.json</term>
        <listitem>
          <para>This file is maintained by jinks to keep track of changes and avoid that local
            changes are overwritten by updates. You should not need to modify it by hand. However,
            it is important that this file is present. Do not remove it and make sure it is
            available in the root collection of your application when installed, e.g. if you deploy
            from a xar package.</para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>context.json</term>
        <listitem>
          <para>Contains the expanded configuration of all profiles used. Maintained by Jinks.
              <emphasis role="bold">Do not remove or modify</emphasis>.</para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>modules</term>
        <listitem>
          <para>The actual application code, written in XQuery, can be found here. Files below the
              <filename>lib</filename> collection should in general not be touched.</para>
          <para>However, profiles can contribute additional XQuery files. Likewise your application
            may need functionality not available out of the box. In general, there are two main
            areas in which a profile or application may contribute XQuery code:</para>
          <variablelist>
            <varlistentry>
              <term>API endpoints</term>
              <listitem>
                <para>Those always come combined with a JSON definition of the endpoint (using the
                  Open API standard), and the naming convention is
                    <filename>[profile-or-app]-api.xql</filename> and
                    <filename>[profile-or-app]-api.json</filename>. For example, the registers
                  profile installs <filename>registers-api.xql</filename> and
                    <filename>registers-api.json</filename>.</para>
              </listitem>
            </varlistentry>
            <varlistentry>
              <term>Templating function modules</term>
              <listitem>
                <para>include helper or utility functions to be used in HTML templates and should go
                  into <filename>modules/templates</filename>.</para>
              </listitem>
            </varlistentry>
          </variablelist>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>templates</term>
        <listitem>
          <para>HTML templates come in two flavours:</para>
          <variablelist>
            <varlistentry>
              <term>page templates</term>
              <listitem>
                <para>contribute a custom HTML page to the application, e.g. a document view for a
                  particular type of edition (see <option>serafin</option> blueprint) adding special
                  features, or a custom browse or landing page. They will usually extend and inherit
                  from one of the base templates.</para>
              </listitem>
            </varlistentry>
            <varlistentry>
              <term>template blocks</term>
              <listitem>
                <para>provide fragments of HTML to be injected into other views. For example, the
                    <option>iiif</option> profile is only adding a IIIF viewer into the right
                  sidebar.</para>
              </listitem>
            </varlistentry>
          </variablelist>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>resources</term>
        <listitem>
          <para>this collection/directory contains CSS stylesheets, Javascript files, i18n
            translation files and most important: ODD files.</para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>doc</term>
        <listitem>
          <para>contains documentation for the profile. This will be shown within jinks if users
            click on the "I" information icon next to a profile.</para>
        </listitem>
      </varlistentry>
      <varlistentry>
        <term>static</term>
        <listitem>
          <para>some profiles allow the application to be transformed into a static snapshot, which
            does not require a database or any other server-side logic. Those profiles usually need
            to provide customized templates for this static version, replacing dynamic functionality
            with static counterparts where possible.</para>
          <para>The collection hierarchy below <filename>static</filename> otherwise mirrors the
            structure described in this chapter.</para>
        </listitem>
      </varlistentry>
    </variablelist>
    <para>For most of the files mentioned above, defined extension points exist in
        <filename>config.json</filename>. This means you have to register the added resource in the
      appropriate location within <filename>config.json</filename>. We'll discuss this in the
      sections below.</para>
    <para>Every profile or application may also add its own configuration parameters to
        <filename>config.json</filename>. By convention those should go into an object below the
        <option>features</option> property. For example, the <option>iiif</option> profile reads its
      configuration items from <code>features.iiif</code>:</para>
    <programlisting language="json" xml:space="preserve">"features": {
  "iiif": {
      "viewer": "pb-tify",
      "base_uri": "https://apps.existsolutions.com/cantaloupe/iiif/2/",
      "enabled": false
  }
}
    </programlisting>
    <section xml:id="anatomy-templates">
      <title>Templated source files</title>
      <para>If you browse through the source code of the profiles shipping with Jinks, you will also
        note a bunch of files having <filename>.tpl</filename> in their name, e.g.
          <filename>profiles/theme-base10/resources/css/jinks-variables.tpl.css</filename>.</para>
      <para>Those are templated files and Jinks will automatically process and expand them while
        copying files. You may rename any file to match the pattern <filename>.tpl.suffix</filename>
        to have it expanded upon installation. What templates are and how you use them is described
        in the next section.</para>
    </section>
    <section xml:id="anatomy-setup">
      <title>XQuery Callbacks</title>
      <para>Whenever generating or updating an application, Jinks will check each profile for an
        XQuery module named <filename>setup.xql</filename>. This module controls the generation or
        update process for the profile. It consists of one or more annotated XQuery functions, which
        are called during the different stages of the process:</para>
      <variablelist>
        <varlistentry>
          <term>%generator:prepare</term>
          <listitem>
            <para>receives the merged configuration map - including all changes applied by other
              profiles earlier in the extension chain - and may return a modified map. Use this to compute and set custom
              properties needed by your profile.</para>
          </listitem>
        </varlistentry>
        <varlistentry>
          <term>%generator:write</term>
          <listitem>
            <para>performs the actual installation. Receives the configuration map as only parameter.</para>
          </listitem>
        </varlistentry>
        <varlistentry>
          <term>%generator:after-write</term>
          <listitem>
            <para>is called after the application has been updated (or installed if it was not generated before).
            Receives the configuration map as first, the path to the root of the target application as second
            parameter.</para>
          </listitem>
        </varlistentry>
      </variablelist>
      <para>If a profile does not have a setup.xql, the default behavious is to recursively copy
        everything in the profile's source folder to the destination, expanding templates on the
        way.</para>
      <para>In TEI Publisher 10, only two profiles: <emphasis>base10</emphasis> and
          <emphasis>theme-base10</emphasis> need a <filename>setup.xql</filename>. Both plug into <code>%generator:after-write</code>
      to perform additional post-processing steps.</para>
    </section>
    <section xml:id="anatomy-bootstrap">
      <title>Bootstrap your own profile</title>
      <para>At the time of writing, all TEI Publisher default profiles are shipped with
          <productname>Jinks</productname>. However, it is also possible to create an external
        profile in the form of an <productname>eXist-db</productname> installable package. Upon
        startup, <productname>Jinks</productname> will search through all packages in the database.
        If a package has a <filename>config.json</filename> with a declared <code>"type"</code>
        property of either <code>"blueprint"</code>, <code>"feature"</code>, <code>"theme"</code> or
          <code>"base"</code>, it will be added to the list of available profiles in the
          <guilabel>Profiles</guilabel> tab. Other than that, a profile's <code>config.json</code>
        looks very much like that of an application, with one exception: where applications list the
        profiles they extend in the <code>"extends"</code> property, a profile does not declare
        this. Instead, it lists the profiles it depends on in the <code>"depends"</code>
        property.</para>
      <para><productname>Jinks</productname> can help to bootstrap the profile: fill out the
        required fields on the <guilabel>Application Configuration</guilabel> tab as usual. On the
          <guilabel>Profiles</guilabel> tab, scroll to the very bottom and enable the
          <guilabel>Create a new profile</guilabel> checkbox. Next to it, you should select the type
        of the profile. Afterwards, choose whatever profiles you would like to add as dependencies
        and change theme or configuration settings as needed.</para>
      <figure>
        <title>New profile option on <guilabel>Profiles</guilabel> tab</title>
        <mediaobject>
          <imageobject>
            <imagedata fileref="jinks-create-profile.png"/>
          </imageobject>
        </mediaobject>
      </figure>
      <para>Clicking <guibutton>Apply</guibutton> will bootstrap the new profile inside the database
        and automatically downloads it as an installable <filename>.xar</filename> package. Now you
        have two options to further work on the profile:</para>
      <orderedlist>
        <listitem>
          <para>inside the database using <productname>eXide</productname></para>
        </listitem>
        <listitem>
          <para>unzip the <filename>.xar</filename> to a directory</para>
        </listitem>
      </orderedlist>
      <para>Using option 1, you'll still have to make sure you backup your profile to the file
        system every now and then (use <guimenuitem>Download App</guimenuitem> in the
          <guimenuitem>Application</guimenuitem> menu). With option 2, you need to build and deploy
        the profile whenever you made changes. The generated Ant build script should generate a new
          <filename>.xar</filename>, which you can then upload to the dashboard.</para>
      <para>If you open the generated <filename>config.json</filename> of the new profile, it may
        look like this:</para>
      <programlisting language="json" xml:space="preserve">{
  "pkg": {
    "abbrev": "my-profile"
  },
  "overwrite": "default",
  "label": "my-profile",
  "type": "blueprint",
  "version": "1.0.0",
  "depends": ["base10","demo-data","theme-base10"],
  "skipSource": [
    "repo.xml",
    "expath-pkg.xml",
    "build.xml"
  ]
}</programlisting>
      <para>Important here is that this configuration has a <code>"type"</code> property, which identifies 
        it as a profile, and the other features used are declared as dependencies.</para>
    </section>
  </section>
  <section xml:id="templates">
    <title>Jinks Templates</title>
    <para>Templates are a key building block of TEI Publisher 10 and appear in two different
      contexts:</para>
    <orderedlist>
      <listitem>
        <para>at generation time to expand the files contributed by the different profiles</para>
      </listitem>
      <listitem>
        <para>at runtime to dynamically render the HTML pages of an application</para>
      </listitem>
    </orderedlist>
    <para>Templates in TEI Publisher 10 use the <link xlink:href="https://github.com/eeditiones/jinks-templates">jinks-templates</link> library,
      which provides a powerful templating system with inheritance, blocks, and XQuery integration.
      Templates are processed server-side. Unlike the templating in earlier TEI Publisher version,
        <productname>jinks-templates</productname> can operate on XML as well as plain text files,
      i.e. the processor can deal with (X)HTML as well as CSS, Javascript or XQuery code. However,
      the following sections will concentrate on HTML templates, because those are the files user
      will be most interested in changing.</para>
    <section xml:id="templates-syntax">
      <title>Templating Syntax</title>
      <para>The jinks-templates library uses a simple but powerful syntax:</para>
      <itemizedlist>
        <listitem>
          <para><code>[% ... %]</code> - Template directives for control structures, includes,
            blocks, and templates</para>
        </listitem>
        <listitem>
          <para><code>[[ ... ]]</code> - Variable interpolation using XQuery expressions</para>
        </listitem>
        <listitem>
          <para><code>---json</code> - Frontmatter markers for configuration (between
              <code>---json</code> and <code>---</code>)</para>
        </listitem>
      </itemizedlist>
      <para>Template directives support common control structures like <code>[% if %]</code>,
          <code>[% for %]</code>, <code>[% include %]</code>, and more. Variable interpolation
        allows you to embed XQuery expressions directly in your templates, with access to the full
        context map and any imported XQuery modules.</para>
      <para>For a full documentation of directives, please refer to the <link xlink:href="https://github.com/eeditiones/jinks-templates">jinks-templating
        README</link>.</para>
    </section>
    <section xml:id="templates-context-map">
      <title>The Context Map</title>
      <para>Every template receives a context map (a JSON object), which it can use to look up
        configuration parameters. The context map is populated from two sources:</para>
      <itemizedlist>
        <listitem>
          <para>the merged <filename>config.json</filename> of the application and all profiles it
            extends. You can see this context in jinks itself if you expand the corresponding
              <guimenuitem>Merged Configuration</guimenuitem> panel below the current application's
            configuration editor.</para>
        </listitem>
        <listitem>
          <para>frontmatter given in the template and any other template it inherits from</para>
        </listitem>
      </itemizedlist>
      <para>Template inheritance and context merging are central concepts in TEI Publisher 10: most
        profiles contribute just a few little fragments to the application, determined by
        configuration variables received in the context. In the simplest case, a page template may
        only contain frontmatter, i.e. it just reconfigures the various features and content blocks
        coming from inherited templates or profiles.</para>
      <section xml:id="templates-context-map-access">
        <title>Accessing the Context</title>
        <para>Within template expressions, the context map can be accessed in two ways:</para>
        <orderedlist>
          <listitem>
            <para>via the <code>$context</code> variable – this is an XQuery map and you can use the
              lookup operator "?" to query for keys, nested maps and arrays. For example, to check
              if the table of contents is enabled, you can write:</para>
            <synopsis>[% if $context?features?toc?enabled %]</synopsis>
          </listitem>
          <listitem>
            <para>via variable mapping – each top level property in the context map is also
              available as a local variable, so above expression could be shortened to:</para>
            <synopsis>[% if $features?toc?enabled %]</synopsis>
          </listitem>
        </orderedlist>
        <para>Note that the second approach will result in an XQuery error if there's no property
          called <option>features</option> in the current context map. Therefore, if you are not
          absolutely sure that the property will always be there, use approach 1, which will never
          fail.</para>
      </section>
    </section>
    <section xml:id="templates-inheritance">
      <title>Template Inheritance</title>
      <para>Templates can extend other templates, creating an inheritance chain. This allows you to
        build complex page layouts by composing simpler templates. The inheritance is specified in
        the JSON frontmatter using the <code>extends</code> directive.</para>
      <para>For example, the inheritance chain for the documentation page you're currently reading
        is as follows:</para>
      <itemizedlist>
        <listitem>
          <para><filename>templates/pages/documentation.html</filename> – Is loaded first, but
            contains only frontmatter and one block to overwrite how breadcrumbs are shown.
            Everything else is inherited via the extended <filename>basic.html</filename>.</para>
        </listitem>
        <listitem>
          <para>
            <filename>templates/pages/basic.html</filename> – Adds the main text view into the
            central content area</para>
        </listitem>
        <listitem>
          <para>
            <filename>templates/layouts/content.html</filename> - Contributes content-specific
            layout with breadcrumbs and table of contents</para>
        </listitem>
        <listitem>
          <para>
            <filename>templates/layouts/base.html</filename> - The root template, defines the
            overall page structure with HTML head, body, and layout areas</para>
        </listitem>
      </itemizedlist>
      <para>The template processor will walk through the entire chain, in the order shown above,
        expanding each template on the way. The initial template at the start of the chain,
          <filename>templates/pages/documentation.html</filename>, looks like this:</para>
      <programlisting language="html" xml:space="preserve">&lt;template&gt;
    ---json
    {
        "templating": {
            "extends": "templates/pages/basic.html"
        },
        "styles": [
            "resources/css/documentation.css"
        ],
        "defaults": {
            "base": "doc/documentation.xml"
        },
        "urls": {
            "template": "documentation/:id?",
            "ignore": "odd,view,path"
        },
        "features": {
            "toc": {
                "enabled": true
            }
        }
    }
    ---
    [% template! breadcrumb %]
    &lt;li&gt;
        &lt;pb-view class="breadcrumbs" src="document1" subscribe="transcription" disable-history="" on-update=""&gt;
            &lt;pb-param name="mode" value="breadcrumb"/&gt;
        &lt;/pb-view&gt;
    &lt;/li&gt;
    [% endtemplate %]
&lt;/template&gt;
</programlisting>
      <para>As you can see, it mainly adds to the configuration, this way changing how inherited
        templates up the chain will process, e.g. by indicating that a table of contents should be
        shown (by default there won't be any).</para>
      <para>There is one template expression, <code>[% template! breadcrumb %]</code>, which
        overrides the default HTML for the breadcrumbs in the toolbar: for the documentation we
        would like to see hierarchical breadcrumbs and we would like to output those via the ODD –
        hence the <tag>pb-view</tag> webcomponent.</para>
    </section>

    <section xml:id="templates-frontmatter-merging">
      <title>Frontmatter Configuration Merging</title>
      <para>As we just learned, each template in the inheritance chain can include JSON frontmatter
        (between <code>---json</code> and <code>---</code> markers). These configurations are merged
        recursively as the inheritance chain is processed. Initially the configuration (passed to
        the first template in the chain) corresponds to the <filename>config.json</filename> of the
        root application, merged with all the <filename>config.json</filename> of the profiles it
        extends.</para>
      <para>It is therefore important to understand how the merging works:</para>
      <itemizedlist>
        <listitem>
          <para><emphasis>Atomic values</emphasis> (strings, numbers, booleans) - Later templates
            overwrite values from earlier templates</para>
        </listitem>
        <listitem>
          <para><emphasis>Maps/Objects</emphasis> - Maps will be processed recursively by merging
            the properties of each incoming into the outgoing map.</para>
        </listitem>
        <listitem>
          <para><emphasis>Arrays</emphasis> - Values are appended with duplicates removed. For
            arrays of maps, deduplication uses the <code>id</code> property if present.</para>
        </listitem>
      </itemizedlist>
      <para>This merging behavior allows child templates to extend or override configuration from
        parent templates. For example, a child template can append additional stylesheets to the
          <code>styles</code> array. Existing array items coming from inherited templates or
        profiles are preserved.</para>
      <para>We can also override a single property in a nested configuration entry. For example, to
        disable the navigation buttons in the toolbar, we can use:</para>
      <programlisting language="json" xml:space="preserve">---json
{
    "features": {
        "toolbar": {
            "navigation": false
        }
    }
}
---</programlisting>
      <para>This will be recursively merged into the initial <code>features.toolbar</code> entry,
        resulting in:</para>
      <programlisting language="json" xml:space="preserve">---json
{
    "features": {
        "toolbar": {
            "enabled": true,
            "zoom": true,
            "navigation": false,
            "progress": {
                "enabled": true,
                "subscribe": "transcription"
            }
        }
    }
}
---</programlisting>
      <para>For sure there will be edge cases when this kind of property merging is not desirable.
        The jinks-templates library provides <link xlink:href="https://github.com/eeditiones/jinks-templates?tab=readme-ov-file#how-context-maps-are-merged">special properties</link> for that (see <code>"$replace"</code>).</para>
    </section>
    <section>
      <title>Preloaded XML Data</title>
      <para>XML documents stored in the application can be preloaded into variables (or context
        properties) to access them in template expressions: if the frontmatter of the template
        contains a <code>data</code> property, it will be processed as an object, mapping variable
        (or property) names to relative paths into the application. The templating tries to resolve
        each relative path to an XML document and declares a top-level property in
          <code>$context</code> with the corresponding name. For example, the frontmatter of
          <filename>profiles/landing-page/templates/index.html</filename> includes:</para>
      <programlisting language="json">"data": {
    "landing": "landing/landing.xml"
}</programlisting>
      <para>This defines a single mapping, though more can be added.
          <filename>landing/landing.xml</filename> is a TEI document containing the sections to be
        rendered for different parts of the landing page. Within the template, information about the
        document as well as its content can be accessed with <code>$landing</code> or
          <code>$context?landing</code>. The value of the variable will be a map with the following
        properties:</para>
      <variablelist>
        <varlistentry>
          <term><code>content</code></term>
          <listitem>
            <para>The root of the document as a document node or the root element of a fragment
              (when using addressing by id)</para>
          </listitem>
        </varlistentry>
        <varlistentry>
          <term><code>path</code></term>
          <listitem>
            <para>The relative path to the document</para>
          </listitem>
        </varlistentry>
        <varlistentry>
          <term><code>odd</code></term>
          <listitem>
            <para>The ODD configured for rendering this document (without the '.odd' suffix)</para>
          </listitem>
        </varlistentry>
        <varlistentry>
          <term><code>view</code></term>
          <listitem>
            <para>The preferred view (<emphasis>div</emphasis>, <emphasis>page</emphasis> …)
              configured for the document</para>
          </listitem>
        </varlistentry>
      </variablelist>
      <para>Within the template, you can use all XQuery expressions to further process the content.
        To render all or parts of it via ODD, call the utility function <code>page:transform</code>,
        e.g.:</para>
      <programlisting language="xml">&lt;div&gt;[[ page:transform($landing?content, map { (: parameters :) }, $landing?odd) ]]&lt;/div&gt;</programlisting>
      <para>If the template is evaluated as part of a route addressing an XML document, the
        associated document will be preloaded by default and will be available as <code>$doc</code>
        or <code>$context?doc</code>. In this case, you do not need to declare an explicit mapping
        in the frontmatter.</para>
      <para>For example, <filename>profiles/docs/templates/pages/osinski.html</filename> will be
        processed when you click on the link to the document <emphasis>Bogactwa mowy
          polskiej</emphasis> in the <emphasis>TEI Publisher 10 Documentation and Demo</emphasis>
        application. The template includes metadata about the document in the right sidebar, which
        is rendered with the following templating fragment:</para>
      <programlisting language="xml">[% template after %]
  &lt;details&gt;
    [[ page:transform($doc?content//tei:teiHeader, map { "mode": "sidebar" }, $doc?odd || ".odd") ]]
  &lt;/details&gt;
[% endtemplate %]</programlisting>
    </section>

    <section xml:id="templates-blocks-and-templates">
      <title>Blocks and Templates</title>
      <para>To make template inheritance really useful, we need a way for templates further down the
        inheritance chain to contribute content to defined locations or placeholders within the
        inherited templates. The template system uses two complementary concepts for content
        composition:</para>
      <variablelist>
        <varlistentry>
          <term><code>[% block name %]</code></term>
          <listitem>
            <para>Defines a placeholder in a parent template where content can be injected. Blocks
              are typically empty in the base template and get filled by child templates. Multiple
              templates in the inheritance chain can contribute content to the same block, which
              will be concatenated.</para>
            <para>If a block is not empty, its content will be used as a fallback in case no other
              template is provided.</para>
          </listitem>
        </varlistentry>
        <varlistentry>
          <term><code>[% template name %]</code></term>
          <listitem>
            <para>Defines content that will be injected into a corresponding <code>[% block name
                %]</code> placeholder. When a template defines a template with a matching name, its
              content fills that block. Multiple templates can contribute to the same block, and
              their content will be concatenated in the order they appear in the inheritance
              hierarchy.</para>
            <para>You may append an additional integer to the template directive to change the
              position at which the content will appear in the block if there's more than one
              template, e.g.:</para>
            <synopsis>[% template after 1 %]</synopsis>
            <para>The integer is used for ordering: templates defining an order number will be
              output first, sorted by the given number. Other templates will come after in the order
              they appear.</para>
          </listitem>
        </varlistentry>
        <varlistentry>
          <term><code>[% template! name %]</code></term>
          <listitem>
            <para>The exclamation mark indicates an override. This replaces any content provided by
              earlier templates in the inheritance chain for this block, rather than appending to
              it. The last <code>[% template! %]</code> always wins and replaces other templates
              occurring before.</para>
          </listitem>
        </varlistentry>
      </variablelist>
      <para>For example, in <filename>templates/layouts/base.html</filename>, you'll find various
        block placeholders like in this snippet:</para>
      <programlisting language="html" xml:space="preserve">&lt;aside class="before hidden-mobile"&gt;
    [% block before %][% endblock %]
&lt;/aside&gt;

&lt;header class="content-top hidden-mobile"&gt;
    [% if $features?toolbar?enabled %]
    [% include "templates/toolbar.html" %]
    [% endif %]
    [% block content-top %][% endblock %]
    [% if $features?toolbar?progress?enabled %]
    &lt;pb-progress subscribe="[[ $features?toolbar?progress?subscribe ]]" indeterminate="indeterminate" /&gt;
    [% endif %]
&lt;/header&gt;

[% block content %][% endblock %]</programlisting>
      <para>This defines three blocks for: the left sidebar, the top of the content area and the
        main content area itself. The content block is treated specially in that it will be filled
        by all remaining content not associated with another block. So to add something into the
        left sidebar as well as some main content, we can use the following child template:</para>
      <programlisting language="html" xml:space="preserve">&lt;template&gt;
  [% template before %]
  &lt;h1&gt;About this document&lt;/h1&gt;
  [% endtemplate %]
  
  &lt;p&gt;This is the main content of the document.&lt;/p&gt;
&lt;/template&gt;</programlisting>
    </section>
    <section xml:id="templates-templates-only-files">
      <title>Template-Only Files for Dynamic Content Injection</title>
      <para>Some profiles use template-only HTML files to add specific panels or components to pages
        without modifying the base templates. These files are wrapped in a <tag>template</tag>
        element and contain only <code>[% template %]</code> definitions, no page structure.</para>
      <para>These template-only files are loaded using the <code>use</code> directive in the
        profile's <filename>config.json</filename>. When a profile specifies files in the
          <code>use</code> array, those templates are automatically loaded and their template
        definitions become available to any page that has the corresponding block
        placeholders.</para>
      <para>For example, the <option>iiif</option> profile uses this pattern to inject a IIIF viewer
        into the right sidebar. The profile's <filename>config.json</filename> includes:</para>
      <programlisting language="json" xml:space="preserve">"templating": {
    "use": [
        "templates/iiif-blocks.html"
    ]
}</programlisting>
      <para>And <filename>templates/iiif-blocks.html</filename> contains:</para>
      <programlisting language="html" xml:space="preserve">&lt;template&gt;
    [% template scripts %]
    [% if ($context?isStatic or exists($context?doc)) and $context?features?iiif?enabled and $context?features?iiif?viewer = "pb-tify" %]
    &lt;script type="module" src="..."&gt;&lt;/script&gt;
    [% endif %]
    [% endtemplate %]

    [% template after %]
    [% if ($context?isStatic or exists($context?doc)) and $context?features?iiif?enabled %]
        [% if $context?features?iiif?viewer = "pb-tify" %]
        &lt;pb-tify subscribe="transcription" emit="transcription"&gt;&lt;/pb-tify&gt;
        [% else %]
        &lt;pb-facsimile .../&gt;
        [% endif %]
    [% endif %]
    [% endtemplate %]
&lt;/template&gt;</programlisting>
      <para>When the IIIF feature is enabled, this template automatically injects the IIIF viewer
        component into the <code>after</code> block (right sidebar) and adds necessary scripts to
        the <code>scripts</code> block, without requiring any changes to the base templates. This
        pattern allows features to be added or removed by simply enabling or disabling them in the
        configuration, making the system highly modular.</para>
      <para>Other profiles that use this pattern include <option>dark-mode</option>,
          <option>timeline</option>, <option>metadata-panel</option>, and <option>annotate</option>,
        each adding their own specific functionality to pages through template-only files.</para>
    </section>
    <section xml:id="templates-importing-helper-functions">
      <title>Importing Helper Functions</title>
      <para>Templates can call XQuery functions from custom modules to perform complex operations or
        access application-specific logic. To make XQuery modules available to templates, you need
        to register them in the profile's <filename>config.json</filename> file under the
          <code>templating.modules</code> property.</para>
      <para>Within a profile, helper modules should be placed in the
          <filename>modules/templates</filename> directory. For example, the <option>base10</option>
        profile includes two helper modules: <filename>modules/templates/page.xqm</filename> and
          <filename>modules/templates/browse.xqm</filename>.</para>
      <para>To register a module, add an entry to the <code>templating.modules</code> object in
          <filename>config.json</filename>. Each module entry uses the module's namespace URI as the
        key, and specifies a <code>prefix</code> (used to call functions in templates) and an
          <code>at</code> path (the location of the module file relative to the profile
        root):</para>
      <programlisting language="json" xml:space="preserve">"templating": {
    "modules": {
        "http://teipublisher.com/ns/templates/page": {
            "prefix": "page",
            "at": "modules/templates/page.xqm"
        },
        "http://teipublisher.com/ns/templates/browse": {
            "prefix": "browse",
            "at": "modules/templates/browse.xqm"
        }
    }
}</programlisting>
      <para>Once registered, functions from these modules can be called directly in templates using
        the prefix. For example, the <code>page:parameter()</code> function from
          <filename>page.xqm</filename> can be used to reliably look up a request parameter:</para>
      <programlisting language="html" xml:space="preserve">&lt;input name="query" type="search" value="[[ page:parameter($context, 'query', ()) ]]"/&gt;</programlisting>
      <para>While not required, it is good practice to pass the template's <code>$context</code> map
        to the helper functions as first parameter, giving them access to all configuration values,
        request parameters, and other context data. This allows them to perform operations that
        would be difficult or impossible to express directly in template syntax, such as complex
        data transformations, permission checks, or API calls.</para>
    </section>
  </section>
  <section xml:id="themes-and-styling">
    <title>Layout, Themes and Styling</title>
    <para>In TEI Publisher 10, HTML templates and styling are covered by different profiles.
      Templates are always part of the profile they functionally belong to. The
        <option>base10</option> profile contains the root templates, which create the general layout
      of the page, while other profiles contribute the views targeted at a particular use case or
      feature.</para>
    <para>Styling, on the other hand, is entirely handled by the selected theme profile. By default
      this is <option>theme-base10</option>. If you remove the dependency on this profile from your
      app, you'll get an unstyled page with just raw HTML.</para>
    <section xml:id="layout">
      <title>Default Page Layout Areas</title>
      <para>To achieve a consistent look and feel across the generated website, the root template in
          <option>base10</option> imposes a certain logical structure in the form of predefined
        areas, which can be filled with content. The assumption is that most pages will obviously
        need a header (for the page menu), a content area, and two areas before and after the
        central view for auxiliary information. Each of the main areas may also need some kind of
        header (e.g. for breadcrumbs or a toolbar).</para>
      <para>However, the base profile does not state how those areas should be laid out on the page.
        This is the responsibility of the theme, which by default renders the areas in a
        three-column layout.</para>
      <para>In detail, the base template (<filename>templates/layouts/base.html</filename>) defines
        the following areas, each corresponding to a templating block, which can be populated by
        templates:</para>
      <variablelist>
        <varlistentry>
          <term>Before Sidebar (<code>before</code>)</term>
          <listitem>
            <para>Contains blocks for the left sidebar area: <itemizedlist>
                <listitem>
                  <para><code>before-top</code> - Navigation items above the sidebar</para>
                </listitem>
                <listitem>
                  <para><code>before</code> - Main sidebar content (commonly used for table of
                    contents)</para>
                </listitem>
              </itemizedlist>
            </para>
          </listitem>
        </varlistentry>
        <varlistentry>
          <term>Main Content (<code>content</code>)</term>
          <listitem>
            <para>Contains blocks for the main content area: <itemizedlist>
                <listitem>
                  <para><code>content-top</code> - Header area above main content (often contains
                    toolbar)</para>
                </listitem>
                <listitem>
                  <para><code>above-content</code> - Content directly above the main content
                    block</para>
                </listitem>
                <listitem>
                  <para><code>content</code> - The main content area (this is where document views
                    are typically rendered)</para>
                </listitem>
                <listitem>
                  <para><code>below-content</code> - Content directly below the main content
                    block</para>
                </listitem>
              </itemizedlist>
            </para>
          </listitem>
        </varlistentry>
        <varlistentry>
          <term>After Sidebar (<code>after</code>)</term>
          <listitem>
            <para>Contains blocks for the right sidebar area: <itemizedlist>
                <listitem>
                  <para><code>after-top</code> - Navigation items above the sidebar</para>
                </listitem>
                <listitem>
                  <para><code>after</code> - Main sidebar content (commonly used for facsimiles,
                    metadata, or other supplementary content)</para>
                </listitem>
              </itemizedlist>
            </para>
          </listitem>
        </varlistentry>
      </variablelist>
      <para>Additionally, there are blocks for the page header (<code>header</code>,
          <code>hero</code>) and for adding styles and scripts to the HTML head
        (<code>styles</code>, <code>scripts</code>).</para>

      <section xml:id="layout-injecting-content">
        <title>Injecting Content into Layout Areas</title>
        <para>As described in the section on <link linkend="templates-blocks-and-templates">templates</link>, child templates use the <code>[% template %]</code> directive with
          the appropriate block name to inject content into any of the layout areas. The content
          defined in the template will be inserted into the corresponding <code>[% block %]</code>
          placeholder in the parent template.</para>
        <para>For example, <filename>templates/layouts/content.html</filename> injects a table of
          contents into the left sidebar by defining a template for the <code>before</code>
          block:</para>
        <programlisting language="html" xml:space="preserve">[% template before %]
[% if $context?features?toc?enabled and exists($context?doc)%]
&lt;h5&gt;
    &lt;pb-i18n key="document.contents"&gt;Contents&lt;/pb-i18n&gt;
&lt;/h5&gt;
&lt;pb-load class="toc" url="api/document/{doc}/contents?target=transcription&amp;amp;icons=true" .../&gt;
[% endif %]
[% endtemplate %]</programlisting>
        <para>This content will appear in the left sidebar defined in <filename>base.html</filename>
          at the location where <code>[% block before %][% endblock %]</code> is placed.</para>
        <para>Similarly, <filename>templates/pages/basic.html</filename> injects the main document
          view into the <code>content</code> block by placing the <tag>pb-view</tag> element
          directly in the template body (content outside of any <code>[% template %]</code>
          directive goes into the <code>content</code> block by default).</para>
        <para>Multiple templates in the inheritance chain can contribute to the same block as
          explained in the previous section.</para>
      </section>
    </section>
    <section xml:id="css-styling">
      <title>Themes and custom CSS styling</title>
      <para>In TEI Publisher 10, all styling is done by one or more <emphasis>theme</emphasis>
        profiles, optionally combined with additional styles required by other profiles for the user
        interface fragments they contribute. After generating an app, the folder
          <code>resources/css</code> will contain all the CSS stylesheets files.</para>
      <para>Out of the box, TEI Publisher 10 comes with a single default theme,
          <emphasis>theme-base10</emphasis>, carefully prepared by a professional designer. The
        future will bring additional themes and users are invited to develop and contribute their own.<note>
          <para><productname>theme-base10</productname> is currently based on a custom build of Pico
            CSS, a minimal CSS framework, which we further stripped down. It provides sensible
            defaults for the most important HTML elements. s</para>
        </note></para>
      <para>To facilitate the modification of frequently customized styling aspects, there are
        several styling definitions that can be be directly configured in
          <filename>config.json</filename> when generating/updating the application, such as the
        logo, the color palette or the fonts. You can find the full list of configurable settings in
        the documentation of the <link xlink:href="../../jinks/profile/theme-base10">theme-base10 profile</link>. Note that this list is not exhaustive and likely to change over time.</para>
      <para>You can overwrite any styling property using the JSON configuration editor
        in Jinks (or by directly editing the <filename>config.json</filename> of your generated application.
        For example, the <emphasis>serafin</emphasis> blueprint changes the styles as follows:</para>
      <programlisting language="json" xml:space="preserve">"theme": {
    "logo": {
        "width": "48px",
        "dark": "../images/base_icon_transparent_background.svg",
        "splash": {
            "dark": "../images/animation_serafin.gif",
            "light": "../images/animation_serafin.gif"
        },
        "light": "../images/base_icon_transparent_background.svg"
    },
    "layout": {
        "search": "before",
        "before": {
            "width": "min(30vw, 420px)"
        }
    },
    "colors": {
        "palettes": {
            "dark": "palette-dark.css"
        },
        "palette": "dark"
    }
}</programlisting>
      <para>This snippet changes the logo, the splash screen, the width of the left sidebar and the color palette.
        Note that we avoid using color codes, but instead refer to a color palette, which has a balanced selection of
        matching colors. In the example above, a new palette named <option>dark</option> is added via 
        <code>colors.palettes</code>.</para>
      
      <section xml:id="themes-and-styling-custom-css">
        <title>Adding CSS Stylesheets</title>
        <para>While some styling aspects can be customized via configuration only, you will likely
          encounter cases for which you would like to add your own CSS. We strongly recommend to not
          change any of the default stylesheets coming from the theme or other profiles. Instead,
          create your own CSS stylesheet and overwrite the default styles where necessary. Not doing
          so will very likely result in conflicts during future updates.</para>
        <para>You can register additional stylesheets by adding them to the top-level
            <option>styles</option> property, which is a JSON array. This can be done directly in
            <filename>config.json</filename>, or via frontmatter. The latter, adding styles via
          frontmatter, has the advantage that the styles will only be loaded for this particular
          view and not pollute the styling of other pages.</para>
        <para>For example, the <emphasis>Documentation + Demo</emphasis> profile does this as
          follows:</para>
        <programlisting language="json" xml:space="preserve">&lt;template&gt;
  ---json
  {
      "templating": {
          "extends": "templates/pages/basic.html"
      },
      "styles": [
          "resources/css/documentation.css"
      ],
      …
  }
  ---
  …
  &lt;/template&gt;</programlisting>
      </section>
      
      
      <section xml:id="css-styling-external">
        <title>External stylesheets</title>
        <para> 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 <code>
            encodingDesc/tagsDecl/rendition</code>), e.g. </para>
        <programlisting language="xml" xml:space="preserve">
                  &lt;rendition source="docbook.css"/&gt;
          </programlisting>
        <para> Styles and classes from that file are loaded into <code>pb-view</code> component and
          thus accessible for its content. </para>
        <para> External stylesheets for <code>pb-view</code> can also be specified via
          <code>load-css</code> component configuration attribute. In this scenario, unlike with ODD
          <code>rendition</code>, regenerating the ODD is not required for changes to the CSS file
          to be applied, otherwise both methods are functionally equivalent. </para>
        
        <programlisting language="html" xml:space="preserve">
                  &lt;pb-view id="view1" src="document1" load-css="odd/docbook.css"/&gt;
          </programlisting>
        
        <para> Broader discussion of using <tag>rendition</tag> for custom styles can be found in
          <link linkend="css-styling-external">this section</link>. </para>
        <!-- shall we discuss CSS shadow part? somewhere -->
      </section>
    </section>
  </section>
  <section xml:id="supported-input-formats">
    <title>Supported XML vocabularies</title>
    <para>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).</para>
    <para> Few specificities of <emphasis>TEI</emphasis> and <emphasis>DocBook</emphasis> are listed
      below, while <emphasis>DOCX</emphasis> is discussed at length in the following section. </para>
    <section xml:id="format-tei">
      <title>TEI</title>
      <para>In principle, any TEI document will be supported by any TEI Publisher-based app, and can
        be displayed with any of the pre-configured blueprints and profiles.</para>
      <para>Nevertheless, certain assumptions are made about encoding of the basic structure of the
        TEI documents for the purpose of navigation:</para>
      <itemizedlist>
        <listitem>
          <para> page beginnings are encoded with <tag>pb</tag>
          </para>
        </listitem>
        <listitem>
          <para> column beginnings are encoded with <tag>cb</tag>
          </para>
        </listitem>
        <listitem>
          <para> structural divisions in the document are encoded with <tag>div</tag> elements
          </para>
        </listitem>
      </itemizedlist>
      <para>We acknowledge that TEI offers other ways to encode these features, e.g. generic
          <tag>milestone</tag> element or specialized numbered division elements like
          <tag>div1</tag>, <tag>div2</tag>. 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. </para>
      <para> We believe our choice represents the most common way of using TEI but, for those who
        followed the path less travelled, the chapter on <link linkend="new-vocabulary-navigation">
          customization</link> briefly discusses how to change relevant functionalities. </para>
    </section>
    <section xml:id="format-docbook">
      <title>DocBook</title>
      <para> DocBook support is demonstrated by this very document you are now reading, <filename>
          documentation.xml</filename>. It is written in DocBook and presented via dedicated
        feature, <emphasis>Docbook support</emphasis> which includes as a default ODD <filename>
          docbook.odd</filename>.</para>
      <!-- TODO: review templating info
        <para> 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
          <guibutton> Settings</guibutton> drawer to see how much impact it has on display. </para>
      <programlisting language="xml" xml:space="preserve">
          &lt;?teipublisher odd="docbook.odd" template="documentation.html" depth="3"?&gt;
        </programlisting>-->
    </section>
    <section xml:id="format-jats">
      <title>JATS (Journal Publishing Tag Library)</title>
      <para> The <emphasis>Jats support</emphasis> feature includes the JATS ODD, which currently
        supports <link xlink:href="https://jats.nlm.nih.gov/publishing/tag-library/1.2/">NISO JATS
          Version 1.2</link>. 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.</para>
      <!-- TODO:  <para>By default, all documents in collection <filename>data/jats</filename> are associated
        with the JATS ODD (see <varname>config:collection-config</varname> in
          <filename>modules/config.xqm</filename>.</para> -->
    </section>

    <section xml:id="docx">
      <title>MS Word DOCX format conversion</title>
      <para> Starting with the version 5.0.0 of the TEI Publisher a new docx handling module is
        available to allow for ingesting documents in <emphasis>docx</emphasis> format. The 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. </para>
      <para>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. </para>


      <section xml:id="docx-intro">
        <title>A word about Word</title>

        <para> 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 <code>$parameters?nstyle(.)</code> function and
          testing if a list is bulleted could be done checking the value of <code>
            $parameters?nstyle(.)/numFmt/@w:val</code>. Full list of available functions and some
          hints how to customize default conversion ODD are provided at the <link linkend="docx-functions">end of this chapter</link>. </para>
        <figure>
          <title>MS Word archive structure</title>
          <mediaobject>
            <imageobject>
              <imagedata fileref="wordStructure.png" width="212px"/>
            </imageobject>
          </mediaobject>
        </figure>

        <variablelist>
          <varlistentry>
            <term>Named tei:* styles</term>
            <listitem>
              <para> Named styles can be strong indicators for the semantics of the text fragment.
                Styles whose name starts with <code>tei:</code> are thus recognized as TEI elements
                with the same name. If a character sequence uses a style called
                  <code>tei:persName</code>, it will be wrapped into a TEI <tag>persName</tag>
                element in the output, e.g. <code>&lt;persName&gt;Johann Wolfgang
                  Goethe&lt;/persName&gt;</code>. A place name should be marked with a style <code>
                  tei:placeName</code> and reconstructed text could be encoded by applying a style
                  <code> tei:supplied</code>. </para>
            </listitem>
          </varlistentry>

          <varlistentry>
            <term>Headings and divisions</term>
            <listitem>
              <para> 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. </para>
              <para> In the first pass, all paragraph styles starting with <code>heading</code>,
                  <code> title</code> or <code>subtitle</code> generate a <tag>tei:head</tag>
                element. The outline level assigned to the heading is recorded as well. </para>
              <para> Subsequently, in a second pass through the generated output, divisions are
                generated based on the outline level: a <tag>div</tag> 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. </para>
            </listitem>
          </varlistentry>

          <varlistentry>
            <term>Lists</term>
            <listitem>
              <para> 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 <code>$parameters?pstyle(.)//outlineLvl/@w:val</code>. </para>
            </listitem>
          </varlistentry>

          <varlistentry>
            <term> Foot- and endnotes</term>
            <listitem>
              <para> Footnotes are translated into TEI note elements. Endnotes are also supported
                and transformed into <code>&lt;note type="endnote"&gt;</code>. </para>
            </listitem>
          </varlistentry>

          <varlistentry>
            <term>Tables</term>
            <listitem>
              <para> Processing of simple tables works very well as well as cells spanning multiple
                colums. Row spans are not implemented yet. </para>
            </listitem>
          </varlistentry>

          <varlistentry>
            <term>Images</term>
            <listitem>
              <para> Embedded images are stored into a subcollection starting with the name of the
                docx file being processed and suffixed with <code>.media</code>, eg.
                  <code>&lt;graphic url="test.docx.media/image1.png"/&gt;</code>
              </para>
            </listitem>
          </varlistentry>
        </variablelist>
      </section>

      <section xml:id="docx-functions">
        <title>ODD for docx</title>
        <para> The ODD used for docx processing can be found in <link xlink:href="../odd-editor.html?odd=docx.odd">docx.odd</link>. 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. </para>
        <para> For testing purposes there is a Word document provided in <filename>
            data/doc/test.docx</filename> 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 <link xlink:href="quickstart.xml#upload">upload section</link> 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. </para>

        <section xml:id="docx-functions-parameters">
          <title>Parameter functions</title>
          <para> Functions below can be used to retrieve styles or other information related to a
            current node. For more usage examples see <link xlink:href="../odd-editor.html?odd=docx.odd">docx.odd</link>
          </para>

          <variablelist>
            <varlistentry>
              <term>cstyle</term>
              <listitem>
                <para>phrase level (characters, words or phrases) styles associated with the current
                  node</para>
                <para> Returns: <code>w:style</code>
                </para>
                <para> Usage example: <code>$parameters?cstyle(.)/name[starts-with(@w:val,
                    'tei:')]</code>
                </para>
              </listitem>
            </varlistentry>

            <varlistentry>
              <term>endnote</term>
              <listitem>
                <para>content of the endnote</para>
                <para> Returns: <code>w:endnote/w:p</code>
                </para>
              </listitem>
            </varlistentry>
            <varlistentry>
              <term>footnote</term>
              <listitem>
                <para>content of the footnote</para>
                <para> Returns: <code>w:footnote/w:p</code>
                </para>
              </listitem>
            </varlistentry>

            <varlistentry>
              <term>link</term>
              <listitem>
                <para>external link</para>
                <para> Returns: <code>rel:Relationship</code>
                </para>
                <para> Usage example: <code>$parameters?link(.)/@Target</code>
                </para>
              </listitem>
            </varlistentry>
            <varlistentry>
              <term>nstyle</term>
              <listitem>
                <para>list style information associated with the current node</para>
                <para> Returns: <code>w:lvl</code>
                </para>
                <para> Usage example: <code>$parameters?nstyle(.)/numFmt</code>
                </para>
              </listitem>
            </varlistentry>

            <varlistentry>
              <term>pstyle</term>
              <listitem>
                <para>paragraph level styles associated with the current node</para>
                <para> Returns: <code>w:style</code>
                </para>
                <para> Usage example: <code>$parameters?pstyle(.)/name[matches(@w:val, 'quote';,
                    'i')]</code>
                </para>
              </listitem>
            </varlistentry>
          </variablelist>
        </section>
      </section>
    </section>
  <section xml:id="new-vocabulary">
    <title>Adding a custom vocabulary</title>
    <para>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:</para>
    <itemizedlist>
      <listitem>
        <para>ODD with processing models</para>
      </listitem>
      <listitem>
        <para>default view and page template</para>
      </listitem>
      <listitem>
        <para>navigation, breadcrumbs and table of contents</para>
      </listitem>
      <listitem>
        <para>search and filtering: full text index definitions, facets and fields</para>
      </listitem>
    </itemizedlist>
    <para>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.</para>
    <para> All other aspects are interconnected and depend on the understanding what constitutes the
      basic unit of the text: TEI primarily considers <emphasis>divisions</emphasis> or <emphasis>
        pages</emphasis>, DocBook rather <emphasis>sections</emphasis>. Therefore navigation for TEI
      document will be switching between <tag>div</tag> s or reconstructed XML fragments between
      subsequent <tag>pb</tag> s, while talking about pages in DocBook documents makes no sense and
        <tag> section</tag> s are the main structural units. </para>
    <para> This structure has its consequences for further aspects: generating TOC in TEI will
      analyze nested <tag>div</tag> / <tag>head</tag> structures but only <tag>section</tag> /
        <tag>title</tag> in DocBook. Likewise, KWIC display in TEI will be showing matches in
        <tag>div</tag> context but <tag>section</tag> 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. </para>
    <para>Sections below will explain where and how to customize these aspects in more
      detail.</para>
    <section xml:id="new-vocabulary-odd">
      <title>ODD</title>
      <para> Create a new, blank ODD file which is not chained to any other ODD and add <tag>
          elementSpec</tag> 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. </para>
      <para>See how it looks in the ODD for DocBook.</para>
      <figure>
        <title>ODD for DocBook</title>
        <mediaobject>
          <imageobject>
            <imagedata fileref="new-vocabulary-odd.png"/>
          </imageobject>
        </mediaobject>
      </figure>
      <para> When adding models into the custom ODD for your vocabulary it is recommended that at
        least one element applies the <parameter>document</parameter> behaviour. Usually it will be
        the top level element or the main content-bearing one (like <tag>article</tag> in DocBook). </para>
      <para> This is not strictly required but for print output via LaTeX or FO the <parameter>
          document</parameter> behaviour specifies default prologue governing basic setup for PDF.
        If you refer to the <filename>docbook.odd</filename> you will note that the same effect is
        achieved by explicitly defining the prologue in the <tag>pb:template</tag> for <parameter>
          article</parameter>. </para>
      <section xml:id="new-vocabulary-foo">
        <title>Case study: foo vocabulary</title>
        <para> Let's consider an imaginary vocabulary called <emphasis>foo</emphasis>. All documents
          in this vocabulary will belong to the <code>http://foo.io</code> namespace. Simple
          document could look as follows: </para>
        <programlisting language="xml" xml:space="preserve">
        &lt;fooStart xmlns="http://foo.io"&gt;
          &lt;foo&gt;My foo document&lt;/foo&gt;
          &lt;bar&gt;About something very important for foo community.&lt;/bar&gt;
        &lt;/fooStart&gt;
        </programlisting>
        <para> Let's save this document in the <filename>playground</filename> collection as
            <filename> foo.xml</filename>. </para>
        <para> Unfortunately a request to retrieve this document in Publisher fails with
            <emphasis>the server did not return any content</emphasis> error message. </para>
        <programlisting>http://localhost:8080/exist/apps/tei-publisher/playground/foo.xml</programlisting>
        <para> Fixing this will require creating a new ODD for <emphasis>foo</emphasis> vocabulary. </para>
        <para> Create a new ODD as described previously. Use <parameter>document</parameter>
          behaviour for <tag>fooStart</tag> element and perhaps <tag>inline</tag> with an <tag>
            outputRendition</tag> set to <parameter>italic</parameter> for <tag>foo</tag> element.
          Please note to specify the ODD for your vocabulary. </para>


        <para> Very bare bones ODD file for a fictional <emphasis>Foo</emphasis> vocabulary could
          look as follows: </para>
        <figure>
          <title>ODD for Foo</title>
          <mediaobject>
            <imageobject>
              <imagedata fileref="foo-odd.png"/>
            </imageobject>
          </mediaobject>
        </figure>

        <para>Or, in XML form:</para>
        <programlisting language="xml" xml:space="preserve">
&lt;schemaSpec start="fooStart" ident="foo" ns="http://foo.io"&gt; 
   &lt;elementSpec ident="foo" mode="add"&gt;
       &lt;model behaviour="inline"&gt;
           &lt;outputRendition&gt;font-style: italic;&lt;/outputRendition&gt;
       &lt;/model&gt;
   &lt;/elementSpec&gt;
   &lt;elementSpec ident="fooStart" mode="add"&gt;
       &lt;model behaviour="document"/&gt;
   &lt;/elementSpec&gt;
&lt;/schemaSpec&gt;
        </programlisting>
        <para> With this in place we could reformulate our request to explicitly specify the ODD to
          use and a <parameter>single</parameter> view. </para>
        <programlisting>http://localhost:8080/exist/apps/tei-publisher/playground/foo.xml?odd=foo&amp;view=single</programlisting>
        <figure>
          <title>foo.xml rendered with foo.odd in single view</title>
          <mediaobject>
            <imageobject>
              <imagedata fileref="foo-single-view.png"/>
            </imageobject>
          </mediaobject>
        </figure>
        <note>
          <title>Note</title>
          <para> It is necessary to use <parameter>single</parameter> view along with the
              <parameter> foo.odd</parameter>. Otherwise, the app default view would be used, which
            in TEI Publisher is normally set to <parameter>div</parameter>. As we already mentioned,
            implementation of view parameters needs to be vocabulary-specific to work. Since
              <emphasis> foo</emphasis> vocabulary doesn't yet have navigation customized, TEI
            Publisher will fall back to TEI and try to locate <tag>tei:div</tag> elements, which
            obviously cannot be found in our test document in foo namespace. </para>

        </note>
      </section>

    </section>
    <section xml:id="new-vocabulary-default-view">
      <title>Default view and page template</title>
      <para> Rendering of the document is governed by a number of parameters, particularly
          <parameter> view</parameter>, <parameter>ODD</parameter> and
          <parameter>template</parameter> : </para>
      <para> Even when these parameters are not explicitly specified, TEI Publisher and apps
        generated from it, will fall back to the default values specified in <filename>
          modules/config.xqm</filename>. </para>

      <itemizedlist>
        <listitem>
          <para> ODD: <code>$config:default-view</code>
          </para>
        </listitem>
        <listitem>
          <para> view: <code>$config:default-view</code>
          </para>
        </listitem>
        <listitem>
          <para> template: <code>$config:default-template</code>
          </para>
        </listitem>
      </itemizedlist>
      <para> Alternative way to specify these would be using a <link linkend="pi-config">processing
          instruction</link> in the foo.xml document itself. </para>
      <programlisting language="xml" xml:space="preserve">
        &lt;?teipublisher odd="foo.odd" view="single" template="view.html"?&gt;
      </programlisting>
    </section>
    <section xml:id="new-vocabulary-lucene">
      <title>Lucene configuration</title>
      <para>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.</para>
      <para> Supporting a new vocabulary, make sure to add its namespace on the <tag>index</tag>
        element in <filename>collection.xconf</filename>. </para>
      <programlisting language="xml" xml:space="preserve">
&lt;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"&gt;
      </programlisting>
      <para>Beyond this minor adjustment, adding a new vocabulary does not differ in creation and
        use of facets and fields.</para>
    </section>
    <section xml:id="new-vocabulary-navigation">
      <title>Navigation</title>
      <para>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.</para>
      <para>
        <filename>modules/navigation.xql</filename> is the main "control room" for all tasks related
        to navigation. You will note that it imports custom modules for all supported vocabularies:
          <emphasis> TEI</emphasis>, <emphasis>JATS</emphasis> and <emphasis>DocBook</emphasis>. All
        requests are dispatched to specialized modules, depending on the namespace of the document
        (cf. <function> config:document-type</function> function). </para>
      <programlisting language="xquery" xml:space="preserve">
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";
      </programlisting>
      <para>Customizing yet unsupported vocabulary will require:</para>
      <itemizedlist>
        <listitem>
          <para> create a new navigation module for the new vocabulary (e.g. <filename>
              navigation-foo.xql</filename> ; it should implement all the functions that <function>
              navigation.xql</function> dispatches to; you can use
              <filename>navigation-tei</filename> as a starting point for customization </para>
        </listitem>
        <listitem>
          <para> import it into <filename>navigation.xql</filename>
          </para>
        </listitem>
        <listitem>
          <para> adjust <function>config:document-type</function> function </para>
        </listitem>
        <listitem>
          <para> adjust <function>nav:get-root</function>
          </para>
        </listitem>
      </itemizedlist>
    </section>
    <section xml:id="new-vocabulary-search">
      <title>Search</title>
      <para> Full text search is realized via the same modular approach that governs navigation.
          <filename> modules/query.xql</filename> is the main "control room", dispatching requests
        to functions in specialized modules. See implementation of <filename>query-db.xql</filename>
        or <filename> query-tei.xql</filename> before creating a dedicated module for your
        vocabulary. Make sure to import your module into <filename>query.xql</filename>. </para>
    </section>

  </section>
  </section>
  

  

  <section xml:id="api">
    <title>Server-side API</title>
    <para> 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 <guibutton>Table of
        Contents</guibutton> button, the corresponding <parameter>pb-load</parameter> 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. </para>

    <para>TEI Publisher, and all applications created with it, use a formal API specification <link xlink:href="../api.html" xlink:show="new">(click this link to see it)</link>, based on the <link xlink:show="new" xlink:href="http://spec.openapis.org/oas/v3.0.3">Open API standard</link>, which 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 <link xlink:href="https://github.com/eeditiones/roaster">roaster</link> and can also be used
      independently.</para>

    <para>The image below presents a section of the core TEI Publisher 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.</para>

    <figure>
      <title>TEI Publisher API page – the <emphasis>odd</emphasis> endpoints</title>
      <mediaobject>
        <imageobject>
          <imagedata fileref="api-spec.png" width="900px"/>
        </imageobject>
      </mediaobject>
    </figure>

    <section xml:id="api-advantages">
      <title>Advantages of the API-based approach</title>
      <itemizedlist>
        <listitem>
          <para>
            <emphasis role="bold">clear specification and easy overview</emphasis>
          </para>
          <para>users and developers will benefit from the clear specification for available
            functionality</para>
        </listitem>
        <listitem>
          <para>
            <emphasis role="bold">customizable</emphasis>
          </para>
          <para>users can easily overwrite and extend existing API endpoints as well as add custom
            ones for project-specific functionality</para>
        </listitem>
        <listitem>
          <para>
            <emphasis role="bold">separation of concerns</emphasis>
          </para>
          <para>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</para>
        </listitem>

        <listitem>
          <para>
            <emphasis role="bold">standard-based</emphasis>
          </para>
          <para>OAS compliance means we are using a well-known and documented standard and can
            benefit from existing tools for writing, testing and generating documentation</para>
        </listitem>
      </itemizedlist>
    </section>
    <section xml:id="api-custom-endpoints">
      <title>Extending the API</title>
      <para>Every Jinks profile or custom application may add additional API endpoints on top of the core API.
        For example, the <emphasis>IIIF profile</emphasis> adds an API endpoint to generate a IIIF manifest from a TEI
        document, and the <emphasis>timeline</emphasis> profile provides endpoints for retrieving timeline data.
        Custom applications and blueprints may implement endpoints in the same way.</para>
      <para>TEI Publisher allows an arbitrary number of Open API configurations, each defining
        different endpoints. Simply provide one or more relevant
     <filename>.json</filename> and <filename>.xql</filename> files for your application or
        profile and register them via the configuration in <filename>config.json</filename>.</para>

      <para>To learn more about the Open API functionality supported by roaster and the different
        fields and parameters available through the passed in <code>$request</code> parameter, see
        the <link xlink:show="new" xlink:href="https://github.com/eeditiones/roaster">README</link>
        of <emphasis>roaster</emphasis>.</para>
    <section xml:id="api-config-example">
      <title>Registering custom API endpoints in <filename>config.json</filename></title>
      <para>To make TEI Publisher aware of your custom Open API specifications, and ensure the endpoints are available, you must register the relevant <filename>.json</filename> Open API definition files in your <filename>config.json</filename> profile or application configuration file. Each entry should specify both the path to your Open API specification file (<filename>.json</filename>) and the implementation module (XQuery route handler).</para>
      <para>As a concrete example, see the snippet from <filename>profiles/iiif/config.json</filename> below. Here, the IIIF profile registers its Open API routes as follows:</para>
      <programlisting language="json" xml:space="preserve">
{
  ...
  "api": [
    {
        "spec": "iiif-api.json",
        "prefix": "iiif",
        "path": "iiif-api.xql",
        "id": "https://e-editiones.org/api/iiif"
    }
  ]
  ...
}
</programlisting>
      <para>In this example, each object in the <code>api</code> array registers an Open API specification with:</para>
      <variablelist>
          <varlistentry>
            <term>id</term>
            <listitem>
              <para>The namespace URI declared by the XQuery module implementing the
                endpoints.</para>
            </listitem>
          </varlistentry>
        <varlistentry>
          <term>prefix</term>
          <listitem>
            <para>A symbolic name used within the system to refer to the endpoint group, and as
                namespace prefix for the XQuery functions to be called. If no XQuery module is
                connected, provide a unique string for the documentation.</para>
          </listitem>
        </varlistentry>
        <varlistentry>
          <term>spec</term>
          <listitem>
            <para>The filename of the Open API specification (<filename>.json</filename> file), relative to the configuration file.</para>
          </listitem>
        </varlistentry>
        <varlistentry>
          <term>path</term>
          <listitem>
            <para>The path to the corresponding XQuery implementation that handles the routes defined in the specification.</para>
          </listitem>
        </varlistentry>
      </variablelist>
        <para>Sometimes you may just want to add an additional endpoint, but reuse existing XQuery
          functions already known to the system. In this case, specify <option>spec</option> and
            <option>prefix</option> only, but leave out <option>path</option> and
            <option>id</option>. For example, the <emphasis>markdown</emphasis> profile contributes
          an endpoint listening on route <code>/markdown/{docid}</code>, but calls the existing view
          operation from module <filename>profiles/base10/modules/lib/api/view.xql</filename>, only
          changing the parameters passed to the function by setting a different default for the HTML
          template to be used. Reusing existing library functions to define custom routes is a
          common pattern, which we will cover in more detail in the next section.</para>
      <para>Open API specifications will be evaluated in the order in which they are given in the
          configuration. Therefore, if two specifications define an endpoint for the same route, the
          second route will win. This way you can overwrite how a route is handled.</para>
    </section>
    </section>
  </section>
  <section xml:id="url-routing">
    <title>URL Routing</title>
    <section xml:id="custom-urls">
      <title>Creating custom URLs</title>
      <para>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 <code>/test/adagia.xml</code> will be handled by the Open API route matching
        the path <code>"/{docid}"</code>, which then calls the XQuery function
          <function>vapi:view</function> to retrieve the HTML template associated with the TEI
        document and return it to the browser:</para>
      <programlisting language="javascript" xml:space="preserve">
"/{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",
		...
	}
}
</programlisting>
 <para>This default can be easily changed to <emphasis>addressing by id</emphasis> in Jinks configuration. Nevertheless 
 some editions may prefer other addressing schemes,
        e.g. using a virtual collection and identifier. For example, the Alfred Escher Briefedition uses URLs like <link xlink:href="https://briefedition.alfred-escher.ch/briefe/B0017" xlink:show="new">https://briefedition.alfred-escher.ch/briefe/B0017</link>. 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 <link xlink:href="https://www.johannconradfischer.com" xlink:show="new">Johann Conrad Fischer</link> 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: <code>/language/year/chapter</code>, e.g. <code>/de/1794/9</code>. Obviously
        implementing a scheme like this requires a bit more tweaking, so we'll concentrate on
        simpler cases like the one in Escher. </para>
      <para>The <productname>TEI Publisher Documentation and Demo</productname> application includes
        one example, which deviates from the default addressing scheme: the <link xlink:href="../encyclopedia" xlink:show="new">Wörterbuch der Philosophischen
          Grundbegriffe</link> represents an early 19th century encyclopedia in German (encoded in
        <link xlink:href="https://dariah-eric.github.io/lexicalresources/pages/TEILex0/TEILex0.html">TEI-Lex0</link>, a customization of TEI targeted at dictionaries and encyclopedias).
        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
          <code>/encyclopedia/{headword}</code>.</para>
      <para>This example needs two route definitions: the first corresponding to the root page
        displayed, i.e. if the user has not selected a headword, the second to represent
        the detail view of a headword. The Open API specification, <link xlink:href="modules/docs-api.json" role="source">modules/docs-api.json</link>, thus has
        configurations for <code>/encyclopedia</code> as well as <code>/encyclopedia/{headword}</code>.
        In both cases we simply copied and modified the configuration for the standard path, i.e.
          <code>"/{docid}"</code>, from <link xlink:href="modules/lib/api.json" role="source">modules/lib/api.json</link>.</para>
      <para>The default endpoint takes various parameter, including two required ones:
          <parameter>docid</parameter> for the path to the TEI document, and
          <parameter>file</parameter> to specify the HTML template to use. For the encyclopedia
        those will always be the same, i.e. <filename>demo/Kirchner-Michaelis-1907.xml</filename> and
        <filename>pages/tei-lex</filename>, so we can pass them as a default value.
        This way we can reuse the existing operation (<function>vapi:view</function>) and don't have
        to write a custom handler function in XQuery!</para>
      <para>The complete definition of the route for a headword in <link xlink:href="modules/docs-api.json" role="source">modules/docs-api.json</link> looks like this:</para>
      <programlisting language="javascript" xml:space="preserve">"/encyclopedia/{search}": {
    "get": {
        "summary": "Show encyclopedia entry matching {search}",
        "description": "Search endpoint used for the encyclopedia example (Damen Conversations Lexikon)",
        "operationId": "vapi:view",
        "x-error-handler": "vapi:handle-error",
        "tags": ["encyclopedia"],
        "parameters": [
            {
                "name": "file",
                "in": "query",
                "schema": {
                    "type": "string",
                    "default": "pages/tei-lex"
                }
            },
            {
                "name": "docid",
                "in": "query",
                "description": "Relative path to the document",
                "required": true,
                "schema": {
                    "type": "string",
                    "default": "demo/Kirchner-Michaelis-1907.xml"
                },
                "allowReserved": true
            },
            {
                "name": "search",
                "in": "path",
                "description": "headword query",
                "required": true,
                "schema": {
                    "type": "string"
                }
            }
        ],
        "responses": {
            "200": {
                "description": "HTML of the page",
                "content": {
                    "text/html": {
                        "schema": {
                            "type": "string"
                        }
                    }
                }
            },
            "404": {
                "description": "The document was not found",
                "content": {
                    "text/html": {
                        "schema": {
                            "type": "string"
                        }
                    }
                }
            }
        }
    }
}</programlisting>
      <para>This handles the server-side routing of requests. However, there's also a client-side
        aspect, which we'll cover in the next chapter.</para>
    </section>
    <section xml:id="client-side-urls">
      <title>Adjusting the client-side URL handling</title>
      <para>With the two routes we set up for the encyclopedia 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.</para>
      <para>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 <link xlink:href="../test/kant_rvernunft_1781.TEI-P5.xml" xlink:show="new">Kant's Kritik</link>,
        the current page displayed will be encoded in the <parameter>root</parameter> parameter. If
        the divisions or pages to navigate by have an <code>xml:id</code>, this will be used instead
        and placed into the <parameter>id</parameter> parameter. The path to the TEI document is
        also tracked (it's the <code>test/kant_rvernunft_1781.TEI-P5.xml</code> part of the URL),
        though you won't see it change while navigating.</para>
      <para>For the encyclopedia example we deviate from this default pattern with the relative URL
        becoming <code>encyclopedia/{headword}</code>. We thus need to inform the client-side
        components about the change, so they know how to store their state into the URL. The Jinks
        configuration schema provides a property <code>urls</code> for this, which has two
        subproperties:</para>
      <variablelist>
        <varlistentry>
          <term><code>template</code></term>
          <listitem>
            <para>A template expression containing placeholders for the parameters to be filled in.
              The template uses the same syntax and library as the popular <link xlink:href="https://expressjs.com/en/guide/routing.html#route-paths" xlink:show="new">Express javascript framework</link>.</para>
          </listitem>
        </varlistentry>
        <varlistentry>
          <term><code>ignore</code></term>
          <listitem>
            <para>A comma-separated list of parameter names which should <emphasis>not</emphasis> be
              reflected in the URL.</para>
          </listitem>
        </varlistentry>
      </variablelist>
      <para>The expression passed to url-template may reference any of the default parameters known
        to TEI Publisher components, in particular <parameter>path</parameter>,
          <parameter>odd</parameter>, <parameter>view</parameter> or <parameter>id</parameter>.
        Additionally, any parameter supplied to a <tag>pb-view</tag> via the <tag>pb-param</tag>
        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 <link xlink:href="https://www.npmjs.com/package/path-to-regexp" xlink:show="new">javascript
          library</link>.</para>
      <para>To handle the URL for the encyclopedia example, we set the URL template to
          <code>encyclopedia/:search?</code>. This injects the <option>search</option> parameter as
        part of the path, e.g. <code>/encyclopedia/Egoismus</code>. The ? after the parameter
        indicates that it is optional. We also do not want the <code>path</code> to the document to
        appear anywhere (it is always the same in the case), so we add it to <code>ignore</code>.
        The resulting configuration snippet would thus look as follows:</para>
      <programlisting language="json" xml:space="preserve">"urls": {
    "template": "encyclopedia/:search?",
    "ignore": "path,odd,view,userParams"
}</programlisting>
      <para>and it is added to the frontmatter of the corresponding HTML template, <link xlink:href="templates/pages/tei-lex.html" role="source">tei-lex.html</link>.</para>
      <note>
        <title>A note on history handling</title>
        <para>It is important that only one central text component on the page writes and reads the
          URL. Usually this will be the main <tag>pb-view</tag>. 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.</para>
        <para>TEI Publisher supports different ways to make one <tag>pb-view</tag> depend on
          another, e.g. via a mapping function (<parameter>map</parameter> attribute). A mapped view
          will never write to the browser history.</para>
        <para>In other cases, to explicitely prevent a dependent <tag>pb-view</tag> from writing to
          the URL, use the attribute <parameter>disable-history</parameter>. To make a
            <tag>pb-view</tag> load its contents <emphasis>after</emphasis> the main text view, set
          attribute <parameter>on-update</parameter> and make sure, the dependent component listens
          to the event channel written by the main component.</para>
      </note>
    </section>
  </section>

  <section xml:id="i18n">
    <title>Language versions</title>
    <para>TEI Publisher is already available in twenty languages and this number increases thanks to
      the engagement of our user community.</para>

    <para>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.</para>
    <para> Thanks to community contributions via <link xlink:href="https://crwd.in/tei-publisher">
        Crowdin</link> 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. </para>
    <para> 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 <filename>de.json</filename> is shown below for illustration. </para>
    <figure>
      <title>Translation JSON file structure</title>
      <mediaobject>
        <imageobject>
          <imagedata fileref="i18n-json-structure.png"/>
        </imageobject>
      </mediaobject>
    </figure>
    <para> In TEI Publisher and in generated apps translation files are by default loaded from CDN
      with <code>pb-components</code>. When it is necessary for a project to add new labels or
      change wording of existing ones, a customization mechanism is described <link linkend="i18n-customization">below</link>. </para>
    <section xml:id="i18n-page-templates">
      <title>Using i18n in page templates</title>
      <para>There are several scenarios for using i18n labels:</para>
      <itemizedlist>
        <listitem>
          <para>directly within HTML element</para>
        </listitem>
        <listitem>
          <para>in an attribute</para>
        </listitem>
        <listitem>
          <para>passed in component-specific structure</para>
        </listitem>
      </itemizedlist>
      <section xml:id="i18n-page-templates-pb-i18n">
        <title> HTML text node with <code>pb-i18n</code>
        </title>
        <para> Any text fragment within HTML element can be considered a target for i18n when
          wrapped in <tag>pb-i18n</tag> component. <tag>pb-i18n</tag> elements are listening for
          events emitted by <tag>pb-lang</tag>. </para>
        <programlisting language="html" xml:space="preserve">
&lt;h3 slot="collapse-trigger"&gt;
   &lt;pb-i18n key="menu.documentation"&gt;Documentation&lt;/pb-i18n&gt;
&lt;/h3&gt;
        </programlisting>
      </section>
      <section xml:id="i18n-page-templates-attributes">
        <title>Attributes (on HTML elements or custom web components)</title>
        <para> When it is necessary to translate the value of an attribute a mechanism based on
            <code> data-</code> attributes is used. Supply additional <code>data-i18n</code>
          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 <code>heading</code>
          attribute that needs to be filled with the translated version of <emphasis>ODD
            Files</emphasis> label. The label is stored in JSON file under <code>odd.files</code>,
          so <code> [heading]odd.files</code> needs to be used for the <code>data-i18n</code>
          attribute. </para>
        <programlisting language="xml" xml:space="preserve">
&lt;paper-card data-i18n="[heading]odd.files" class="odds" heading="ODD Files"&gt;
   &lt;div class="card-content"&gt; ... content of the ODD list &lt;/div&gt;
&lt;/paper-card&gt;
        </programlisting>
        <para> When <tag>pb-lang</tag> is switched to Spanish, the <tag>paper-card</tag> heading
          will read <emphasis>Archivos ODD</emphasis> instead of <emphasis>ODD Files</emphasis>. </para>
        <figure>
          <title> Output for <tag>paper-card</tag> with translated <code>@heading</code>
          </title>
          <mediaobject>
            <imageobject>
              <imagedata fileref="i18n-attribute.png" width="300px"/>
            </imageobject>
          </mediaobject>
        </figure>
      </section>
      <section xml:id="i18n-page-templates-properties">
        <title>Special web component properties configured via attributes</title>
        <para> Some web components accept more complex configuration options via arrays passed in
          attributes. For example, <tag>pb-browse-docs</tag> 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
            <tag> pb-lang</tag>. Therefore i18n translation keys like
            <emphasis>browse.title</emphasis> or <emphasis> browse.author</emphasis> 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. </para>
        <programlisting language="html" xml:space="preserve">
&lt;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"&gt;
  &lt;pb-paginate slot="toolbar" id="paginate" per-page="10" range="5" emit="docs" subscribe="docs"&gt;&lt;/pb-paginate&gt;
&lt;/pb-browse-docs&gt;
         </programlisting>
      </section>
    </section>

    <section xml:id="i18n-customization">
      <title>Project specific i18n files</title>
      <para>It is a common need that projects will need their own internationalized labels for menu
        items, dialogs and other user interface elements.</para>
      <para>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:</para>
      <programlisting language="html" xml:space="preserve">&lt;pb-page locales="resources/i18n/{{ns}}/{{lng}}.json"&gt;</programlisting>
      <para> The path expression requires placeholders for two parameters <parameter>ns</parameter>
        and <parameter>lng</parameter> : </para>
      <variablelist>
        <varlistentry>
          <term>lng</term>
          <listitem>
            <para> the language code for a selected language, e.g. <code>de</code> or
                <code>fr</code>
            </para>
          </listitem>
        </varlistentry>
        <varlistentry>
          <term>ns</term>
          <listitem>
            <para> 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 <code>app</code>, though this can be configured. </para>
          </listitem>
        </varlistentry>
      </variablelist>
      <para> So given above configuration, TEI Publisher will search for a custom language file for,
        say, French in <code>resources/i18n/app/fr.json</code>. If you prefer a flat directory
        structure, you could change the <parameter>locale</parameter> to <code>
          resources/i18n/{{ns}}_{{lng}}.json</code> and TEI Publisher will look for a file <code>
          resources/i18n/app_fr.json</code>. </para>
      <para> You may also define additional namespaces to be searched with the <parameter>
          locale-fallback-ns</parameter> parameter: </para>
      <programlisting language="html" xml:space="preserve">&lt;pb-page locales="resources/i18n/{{ns}}/{{lng}}.json"
        locale-fallback-ns="app my-module"&gt;</programlisting>
      <para> which means that TEI Publisher will search for labels in the <code>my-module</code>
        namespace first, then falling back to the <code>app</code> namespace, and if the label could
        still not be found, using TEI Publisher's default namespace. The latter is called <code>
          common</code> and should not be overwritten. </para>
      <para> Listing below demonstrates a fictional <filename>en.js</filename> with a custom set of
        labels. A new top-level key has been added as well as 3 subkeys for the <code>menu</code>
        section. Now the project has access to a number of new i18n keys: <code>menu.about</code>,
          <code> menu.contact</code>, <code>menu.statute</code> and <code>greeting</code>. </para>
      <para> Furthermore, a value for <code>menu.documentation</code> 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. </para>
      <programlisting language="js" xml:space="preserve">
{
  "menu": {
    "documentation": "Docu",
    "about": "About",
    "contact": "Contact",
    "statute": "Statute"
    },
  "greeting": "Welcome"
}
      </programlisting>
      <para/>
    </section>
  </section>

  
  <section xml:id="search">
  <title>Search</title>
  <para>TEI Publisher (as eXist-db) make extensive use of the <productname>Lucene</productname> indexing engine to implement filtering and ordering of data. In particular, all search-related features heavily depend on full text, facets and fields of the Lucene index. It is therefore paramount to specify these correctly for your data collection.</para>
  <para>In the context of the TEI Publisher application, when searching, we are applying certain criteria to the collection of all available entries. As a result, we select only entries matching the filtering criteria. By entries we usually mean elements from the <code>data-default</code> collection, typically represented by individual TEI files, less often <emphasis>virtual documents</emphasis>. Either way, the data collection needs an index configuration, matching the kinds of queries we expect to run.</para>
  <para>From the eXist database perspective there are 3 types of query criteria, which can be applied in conjunction:</para>
      <variablelist>
        <varlistentry>
          <term><emphasis>full text</emphasis> queries</term>
          <listitem>
            <para/><para>matching the text content of the entry, for which the full text index is defined; therefore, if we want to search in the entire TEI document (both metadata and transcription), we need an index on <code>TEI</code>, if only the transcription part, on <code>TEI/text</code></para>
            <para>full text queries can match entire words exactly, but we may also use wildcard characters (<code>?</code> and <code>*</code>) to search for patterns, e.g. <code>ben*</code> would match anything starting with <emphasis>ben</emphasis>, like <emphasis>benefactor</emphasis>, <emphasis>benevolent</emphasis> or the name <emphasis>Ben</emphasis></para>
          </listitem>
        </varlistentry>
        <varlistentry>
          <term><emphasis>field</emphasis> queries</term>
          <listitem>
            <para>similar to the full text query, but searching only through the predefined field, which can be defined as necessary; for example, we can associate a field called <code>abstract</code> with a <code>TEI/text</code> node and define it as <code>&lt;field name="abstract" expression="ancestor::tei:TEI//tei:abstract"/&gt;
</code></para>
            <para>Please note that the field is always defined in relation to the node, for which the index is defined</para>
          </listitem>
        </varlistentry>
        <varlistentry>
          <term>facet queries</term>
          <listitem>
            <para>like a fields, a facet can be defined with an arbitrary content, which will be attached to the indexed parent node; main difference is it can be only used for exact checks: only if the indexed node has the exact facet value associated, it will be matched by the query</para>
          </listitem>
        </varlistentry>
  </variablelist>
  <para>Illustration above shows user interface elements related to all query types. Facets are selected with checkboxes, while full-text and field queries are input in the <guibutton>Search</guibutton> box at the top of the sidebar. The <guibutton>Query scope</guibutton> allows users to choose between default full-text search (here called just <emphasis>content</emphasis>, and more constrained field searches.</para>
   <figure>
      <title>Search options: full-text, fields and facets</title>
      <mediaobject>
        <imageobject>
          <imagedata fileref="search-options.jpg"/>
        </imageobject>
      </mediaobject>
    </figure>
  <section xml:id="index-configuration">
      <title>Index configuration</title>
     
          <para> The <filename>collection.xconf</filename> tells eXist database how to index the collection.
            The default configuration in TEI Publisher creates several Lucene full-text indexes, the most 
            important one for TEI associated with <tag>tei:text</tag>. It has a number of fields and facets attached.
            </para>
            <para>
            Every field and facet must have an
              <parameter>expression</parameter> attribute. The expression is an arbitrary
            XPath/XQuery expression. For every element being indexed, the expression is evaluated once
            and the result defines the values which will be associated with the indexed elements. </para>
            <para>Apart from <parameter>expression</parameter>, fields require a <parameter>name</parameter>, 
            while facets need a <parameter>dimension</parameter>.</para>
          <note><para> For a detailed description of how full-text indexes and facets are defined in the <filename>
              collection.xconf</filename>, please refer to the <link xlink:show="new" xlink:href="http://exist-db.org/exist/apps/doc/lucene">eXist documentation</link>.
          </para></note>
          
        <para> If you open the default <filename>collection.xconf</filename>, you'll see that most
            facet or field expressions call a function <function>nav:get-metadata</function>. This function
            is declared in <filename>index.xql</filename> helper file. By externalizing most of the code into a
            separate function, we can keep the index configuration clean and short. </para>
        <note><para> The default <filename>index.xql</filename> already does some advanced
            preprocessing, for example for the "genre" facet: each of the sample documents
            references a central taxonomy (contained in <filename>data/taxonomy.xml</filename>). The
            references are resolved at indexing time by following the <tag>catRef</tag> element's
              <parameter>@target</parameter> attribute. Note that we create a hierarchical facet,
            because e.g. "Philosophy" is a sub-category of "Prose". The code in function <function>
              idx:get-genre</function> will automatically include the super-category. </para></note>
              
      <para>Example below shows an excerpt from TEI Publisher standard index for the <code>TEI/text</code> nodes. 
      Please note that sometimes both fields and facets are defined under the same field name as the facet dimension. 
      They may, but don't necessary need to be computed in the same way, for example the date field holds a string value, 
      while the facet dimension is a sequence of year-month-day items, which is used for the hierarchical facet.</para>
      <programlisting language="xml" xml:space="preserve">
&lt;text match="/tei:TEI/tei:text"&gt;
    &lt;field name="language" expression="nav:get-metadata(ancestor::tei:TEI, 'language')"/&gt;
    &lt;field name="person" expression="nav:get-metadata(ancestor::tei:TEI, 'person')"/&gt;
    &lt;field name="date" expression="nav:get-metadata(ancestor::tei:TEI, 'date')"/&gt;
    &lt;field name="file" expression="util:document-name(.)"/&gt;
    &lt;field name="text" expression="."/&gt;
    
    &lt;facet dimension="genre" expression="nav:get-metadata(ancestor::tei:TEI, 'genre')" hierarchical="yes"/&gt;
    &lt;facet dimension="language" expression="nav:get-metadata(ancestor::tei:TEI, 'language')"/&gt;
    &lt;facet dimension="person" expression="nav:get-metadata(ancestor::tei:TEI, 'person')"/&gt;
    &lt;facet dimension="date" expression="nav:get-metadata(ancestor::tei:TEI, 'date') =&gt; tokenize('-')" hierarchical="yes"/&gt;
&lt;/text&gt;
      </programlisting>
  </section>
  <section xml:id="facets">
    <title>Facets</title>
    <para>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. TEI
      Publisher provides default index configuration which can be extended to match custom-defined facets.</para>
    
    <para> From a user perspective, the main concept behind facets is the <emphasis>drill
        down</emphasis> : initially the user sees all facet values associated with the set of
      search results displayed. The number behind each value denotes the number of
      items in the set, matching this particular facet. As the user selects a facet value, the set
      necessarily becomes smaller, as the non-matching facet values disappear and the numbers
      adjust accordingly. </para>
    <para> Facets 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 an
      example of facets in action, just go to the <link xlink:href="/exist/apps/tei-publisher/browse.html" xlink:show="new">Browse</link> page of Documentation and Demo. </para>
    <para>If you would like to configure additional facets, you need to prepare relevant indexes as described in 
    <link linkend="index-configuration">index configuration</link> chapter and additionally edit the <code>facets-config.xqm</code></para>
    
          <para> While the index configuration is responsible for the server-side creation of facets, we need a
            place to define how facets should be displayed in the user interface. The <code>facets-config</code>
            configuration module: <filename>config.xqm</filename> declares a variable <parameter>
              $config:facets</parameter>. It should contain an array of maps, where each map defines
            the settings for one dimension, e.g.: </para>
          <programlisting language="xquery" xml:space="preserve">
(:
 : Display configuration for facets to be shown in the sidebar. The facets themselves
 : are configured in the index configuration, collection.xconf.
 :)
declare variable $facets-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()
    },
];
</programlisting>
          <para>The map properties are as follows:</para>
          <variablelist>
            <varlistentry>
              <term>dimension</term>
              <listitem>
                <para> The name of the dimension. Should correspond to the value of the <parameter>
                    @dimension</parameter> attribute used in <filename>collection.xconf</filename>
                </para>
              </listitem>
            </varlistentry>
            <varlistentry>
              <term>heading</term>
              <listitem>
                <para>The heading to display above the facet values</para>
              </listitem>
            </varlistentry>
            <varlistentry>
              <term>max</term>
              <listitem>
                <para> Maximum number of facet values to be displayed initially. More can be shown
                  if the user clicks on the <guilabel>Show All</guilabel> checkbox. Pass an empty
                  sequence, i.e. (), to not limit the number and hide the checkbox. </para>
              </listitem>
            </varlistentry>
            <varlistentry>
              <term>hierarchical</term>
              <listitem>
                <para> 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 <filename>
                    collection.xconf</filename>
                </para>
              </listitem>
            </varlistentry>
            <varlistentry>
              <term>output</term>
              <listitem>
                <para>A function which can be used to process the facet value before display. The
                  facet label will be replaced by whatever the function returns.</para>
                <para>The function may accept a single (taking the current facet value), or two
                  parameters (current facet value and selected UI language).</para>
              </listitem>
            </varlistentry>
            <varlistentry>
              <term>source</term>
              <listitem>
                <para>In addition to checkboxes, an autocomplete <emphasis>combo box</emphasis> can be displayed into which users can
                  type to search for and select a facet. This is in particular useful for
                  long lists of possible facet values. The <code>source</code> 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
                    <filename>profiles/base10/modules/lib/api/search.xql</filename>,
                  <code>sapi:list-facets</code>.</para>
                <para>If an <code>output</code> function is provided, facet labels are passed to it
                  before display. Note that the combo box will not work with hierarchical
                  facets.</para>
              </listitem>
            </varlistentry>
    </variablelist>
  </section>

  </section>

  <section xml:id="production">
    <title>Hosting</title>
    <para>Regardless of the installation type, TEI Publisher always runs on an <link xlink:show="new" xlink:href="https://exist-db.org">eXist-db database</link> 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 <link xlink:show="new" xlink:href="https://exist-db.org/exist/apps/doc/production_good_practice">Production Use – Good Practice</link> 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.</para>
    <section xml:id="proxy">
      <title>Running behind a proxy</title>
      <para>To set up a proxy, we suggest looking at the docker compose configuration we provide. It
        includes <link xlink:href="https://github.com/eeditiones/teipublisher-docker-compose/tree/master/conf">configuration templates</link> for the nginx proxy. More general information about proxy
        servers and eXist-db can be found in the article <link xlink:show="new" xlink:href="https://exist-db.org/exist/apps/doc/production_web_proxying">Proxying eXist-db
          behind a Web Server</link>.</para>
      <para>What does a proxy do for you? It can:</para>
      <orderedlist>
        <listitem>
          <para>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 <link xlink:href="https://www.briefedition.alfred-escher.ch/">public URL</link> 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.</para>
        </listitem>
        <listitem>
          <para>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.</para>
        </listitem>
        <listitem>
          <para>cache specific pages, so TEI Publisher does not need to transform TEI to HTML every
            time</para>
        </listitem>
      </orderedlist>
      <para>In the following sections we'll discuss specific settings you should pay attention to
        when running TEI Publisher behind a proxy.</para>
      <section xml:id="context-path">
        <title>Context paths</title>
        <para>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 <code>/exist/apps/my-edition/</code>
          (we call this the <emphasis>context path</emphasis>). 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.</para>
        <para>TEI Publisher based apps allow developers to control this behaviour via a special
          variable in <code>modules/config.xqm</code> called
          <code>$config:context-path</code>.</para>
        <para>The default setting for <code>$config:context-path</code> is determined as
          follows:</para>
        <procedure>
          <step>
            <para>if a Java system property called <code>teipublisher.context-path</code> is set,
              use its value as context path</para>
          </step>
          <step>
            <para>otherwise look at the HTTP request header <code>X-Forwarded-Host</code> and if
              present, assume that we're running behind a proxy and the context path should be
              empty</para>
          </step>
          <step>
            <para>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
                <code>/exist/apps/my-edition/</code></para>
          </step>
        </procedure>
        <para>This procedure should work for most cases, so manually adjusting
            <code>$config:context-path</code> should rarely be necessary.</para>
      </section>
      <section xml:id="caching">
        <title>Caching</title>
        <para>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 <code>If-Modified-Since</code> 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.</para>
        <para>To enable this feature, set the variable <code>$config:enable-proxy-caching</code> to
          true.</para>
        <note>
          <para>At the time of writing, only the most important API calls in TEI Publisher support
              <code>If-Modified-Since</code>. Those include the API call for displaying a single
            page or division, which is the most frequently called operation.</para>
        </note>
      </section>
    </section>
    <section xml:id="hosting">
      <title>Hosting Options</title>
      <para>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.</para>
      <para>Some options are:</para>
      <variablelist>
        <varlistentry>
          <term>dedicated server</term>
          <listitem>
            <para>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.</para>
          </listitem>
        </varlistentry>
        <varlistentry>
          <term>dockerized installation</term>
          <listitem>
            <para>we provide a ready-to-use configuration including TEI Publisher, a proxy and the
              named entity recognition service in the <link xlink:show="new" xlink:href="https://github.com/eeditiones/teipublisher-docker-compose">teipublisher-docker-compose</link> Github repository. The readme describes how to
              customize this configuration for your own custom edition.</para>
            <para>To use this option you need to find a hosting provider, which supports running a
              dockerized architecture with <emphasis>docker compose</emphasis> (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. </para>
          </listitem>
        </varlistentry>
        <varlistentry>
          <term>static site</term>
          <listitem>
            <para>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 <link xlink:show="new" xlink:href="https://www.e-editiones.org/posts/community-event-going-static/">Generating a high voltage site by going static</link> describes how such a static
              site can be generated and discusses in detail the advantages and drawbacks of this
              solution.</para>
          </listitem>
        </varlistentry>
        <varlistentry>
          <term>all-inclusive hosting options</term>
          <listitem>
            <para>in cooperation with e-editiones, <link xlink:href="https://www.archives-online.org/">Archives Online</link> provides a
              complete hosting solution for scholarly editions based on TEI Publisher and IIIF on
                <link xlink:show="new" xlink:href="https://sources-online.org/">sources-online.org</link>. This covers long-term maintenance and support of an
              edition project. If you are interested in having an edition hosted, please contact
                <link xlink:href="info@archives-online.org">Archives Online</link>.</para>
          </listitem>
        </varlistentry>
      </variablelist>
    </section>
  </section>
</article>