<?xml version='1.0'?>

<!--********************************************************************
Copyright (C) 2018-2026  Robert A. Beezer

This file is part of PreTeXt.

PreTeXt is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 2 or version 3 of the
License (at your option).

PreTeXt is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with PreTeXt.  If not, see <http://www.gnu.org/licenses/>.
*********************************************************************-->

<!-- http://pimpmyxslt.com/articles/entity-tricks-part2/ -->
<!DOCTYPE xsl:stylesheet [
    <!ENTITY % entities SYSTEM "entities.ent">
    %entities;
]>

<!-- Identify as a stylesheet -->
<!-- We choose to not include a default namespace       -->
<!-- (in particular  http://www.w3.org/1999/xhtml),     -->
<!-- even if this complicates adding namespaces onto    -->
<!-- derivatives, such as HTML destined for EPUB output -->
<!-- xmlns="http://www.w3.org/1999/xhtml"               -->
<xsl:stylesheet
    xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0"
    xmlns:xml="http://www.w3.org/XML/1998/namespace"
    xmlns:pi="http://pretextbook.org/2020/pretext/internal"
    xmlns:exsl="http://exslt.org/common"
    xmlns:date="http://exslt.org/dates-and-times"
    xmlns:str="http://exslt.org/strings"
    extension-element-prefixes="pi exsl date str"
>

<!-- Standard conversion groundwork -->
<xsl:import href="./publisher-variables.xsl"/>
<xsl:import href="./pretext-assembly.xsl"/>
<xsl:import href="./pretext-common.xsl"/>

<!-- With @indent="yes" the (intermediate) file is much easier to study    -->
<!-- and debug, but it introduces whitespace we can not (or do not want    -->
<!-- to) control for.  The situation is a single isolated sentence that    -->
<!-- is entirely a font change.  Here "isolated" means it becomes an       -->
<!-- entire "segment", such as being between two "displays" when breaking  -->
<!-- up a paragraph.  For example, an entire sentence could be in italics, -->
<!-- thus leading to a "segment" with a child "italic" and nothing else.   -->
<!-- The indentation provided introduces whitespace where we are expecting -->
<!-- mixed content.  In old parlance, we expect a "segment" to be "tight". -->
<!-- We saw this just twice in all of AATA (2023-04-07) where a lone "m"   -->
<!-- (plus absorbed punctuation) was caught between displays in a          -->
<!-- paragraph, and the whitespace bled into a diff when the previous      -->
<!-- commit led to the @indent suddenly being effective.                   -->

<xsl:output method="xml" indent="no" encoding="UTF-8"/>

<xsl:variable name="exercise-style" select="'static'"/>

<!-- Not so much "include" as "manipulate"            -->
<xsl:param name="math.punctuation.include" select="'all'"/>

<!-- Developer-only.  Braille arriving from Speech Rule Engine     -->
<!-- (mathematics) is Unicode braille cells (U+2800 through        -->
<!-- U+283F).  With "late" (the default) those cells ride through  -->
<!-- the preprint intermediate unchanged and become BRF ASCII      -->
<!-- symbols in the renderer.  With "early" the conversion to BRF  -->
<!-- ASCII symbols happens here, so the preprint file itself is    -->
<!-- readable by anyone fluent in BRF, at no change to the final   -->
<!-- BRF.  The root element of the preprint records the choice so  -->
<!-- the renderer can react.                                       -->
<xsl:param name="debug.brf.symbols" select="'late'"/>
<xsl:variable name="brf-symbols">
    <xsl:choose>
        <xsl:when test="($debug.brf.symbols = 'early') or ($debug.brf.symbols = 'late')">
            <xsl:value-of select="$debug.brf.symbols"/>
        </xsl:when>
        <xsl:otherwise>
            <xsl:message>PTX:FALLBACK: the "debug.brf.symbols" string parameter must be "early" or "late", not "<xsl:value-of select="$debug.brf.symbols"/>", using "late" instead</xsl:message>
            <xsl:text>late</xsl:text>
        </xsl:otherwise>
    </xsl:choose>
</xsl:variable>
<xsl:variable name="b-braille-symbols-early" select="$brf-symbols = 'early'"/>

<!-- The 64 Unicode braille cells, in numerical order, and their   -->
<!-- BRF ASCII equivalents, generated with liblouis, which is what -->
<!-- the renderer employs for the identical conversion when the    -->
<!-- cells ride through as Unicode ("late").  Exception: the blank -->
<!-- cell U+2800 maps to a NO-BREAK SPACE, not to a plain space:   -->
<!-- it reads as a space, but the renderer can still distinguish   -->
<!-- a (non-breaking) blank cell from an authored space when it    -->
<!-- makes line-breaking decisions, and it becomes a plain space   -->
<!-- in the final output, exactly as a blank cell does.            -->
<xsl:variable name="unicode-braille-cells" select="'&#x2800;&#x2801;&#x2802;&#x2803;&#x2804;&#x2805;&#x2806;&#x2807;&#x2808;&#x2809;&#x280A;&#x280B;&#x280C;&#x280D;&#x280E;&#x280F;&#x2810;&#x2811;&#x2812;&#x2813;&#x2814;&#x2815;&#x2816;&#x2817;&#x2818;&#x2819;&#x281A;&#x281B;&#x281C;&#x281D;&#x281E;&#x281F;&#x2820;&#x2821;&#x2822;&#x2823;&#x2824;&#x2825;&#x2826;&#x2827;&#x2828;&#x2829;&#x282A;&#x282B;&#x282C;&#x282D;&#x282E;&#x282F;&#x2830;&#x2831;&#x2832;&#x2833;&#x2834;&#x2835;&#x2836;&#x2837;&#x2838;&#x2839;&#x283A;&#x283B;&#x283C;&#x283D;&#x283E;&#x283F;'"/>
<xsl:variable name="ascii-braille-cells">&#xA0;a1b'k2l`cif/msp"e3h9o6r~djg&gt;ntq,*5&lt;-u8v.%{$+x!&amp;;:4|0z7(_?w}#y)=</xsl:variable>

<!-- Convert Unicode braille cells to BRF ASCII symbols, when      -->
<!-- elected ("early"); the text is otherwise undisturbed.         -->
<!-- The conversion is all-or-nothing per text: when a             -->
<!-- construction has no braille translation, Speech Rule Engine   -->
<!-- can leave print residue among the cells, and such a mixture   -->
<!-- must ride along whole (cells as Unicode) so the renderer      -->
<!-- gives it the identical late treatment under either election.  -->
<xsl:template name="brf-symbols-filter">
    <xsl:param name="text"/>
    <xsl:choose>
        <xsl:when test="$b-braille-symbols-early and (translate($text, concat($unicode-braille-cells, ' &#xa;&#x9;&#xd;&#xa0;'), '') = '')">
            <xsl:value-of select="translate($text, $unicode-braille-cells, $ascii-braille-cells)"/>
        </xsl:when>
        <xsl:otherwise>
            <xsl:value-of select="$text"/>
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>

<!-- ############################## -->
<!-- Incorporate (Meld) Mathematics -->
<!-- ############################## -->

<!-- We do a pass (similar to those in the "pretext-assembly.xsl"   -->
<!-- stylesheet.  Purpose is to incorporate Nemeth braille versions -->
<!-- of mathematics, produced by MathJax/Speech RTule Engine.       -->

<!-- Necessary to get pre-constructed Nemeth braille for math elements. -->
<!-- This file of math representations will come from another process   -->
<!-- that involves mathJax and Speech Rule Engine (SRE).                -->
<!-- Note: this is a manual step during development.                    -->
<xsl:param name="mathfile" select="''"/>
<xsl:variable name="math-repr"  select="document($mathfile)/pi:math-representations"/>

<!-- Default xerox machine for "meld-math" pass -->
<xsl:template match="node()|@*" mode="meld-math">
    <xsl:copy>
        <xsl:apply-templates select="node()|@*" mode="meld-math"/>
    </xsl:copy>
</xsl:template>

<!-- $math-repr is a "global" variable with "pi:math" elements -->
<xsl:key name="math-elts" match="pi:math" use="@id"/>

<!-- Replace math elements with a substructure: -->
<!--     math-original: the guts, simply xeroxed, necessary for -->
<!--         examining simple situations which do not require a -->
<!--         switch to Nemeth, or use simpler indicators        -->
<!--     math-nemeth: unicode from SRE                          -->
<!-- NB: after a  md[mrow]  goes through MathJax/SRE there is   -->
<!-- no "mrow" left.  So they are absent in "math-nemeth".  They -->
<!-- *are* present in "math-original" but that introduces a new  -->
<!-- element in-between "md" and "mrow", so matches on           -->
<!-- "md[mrow]" can be problematic here (and perhaps elsewhere). -->
<xsl:template match="m|md" mode="meld-math">
    <!-- preserve author's element -->
    <xsl:copy>
        <!-- preserve attributes -->
        <xsl:apply-templates select="@*" mode="meld-math"/>
        <!-- get braille from representations file -->
        <xsl:variable name="id">
            <xsl:apply-templates select="." mode="unique-id"/>
        </xsl:variable>
        <math-original>
            <xsl:apply-templates select="node()|@*" mode="meld-math"/>
        </math-original>
        <math-nemeth>
            <xsl:for-each select="$math-repr">
                <xsl:value-of select="key('math-elts', $id)/div[@class = 'braille']"/>
            </xsl:for-each>
        </math-nemeth>
    </xsl:copy>
</xsl:template>

<!-- An additional pass melds math markup, starting from $root, the  -->
<!-- final tree from -assembly.  This stylesheet then works from the -->
<!-- melded tree, $melded-root, for its $docinfo and $document-root. -->
<xsl:variable name="math-meld-rtf">
    <xsl:apply-templates select="$root" mode="meld-math"/>
</xsl:variable>
<xsl:variable name="melded-math" select="exsl:node-set($math-meld-rtf)"/>

<xsl:variable name="melded-root" select="$melded-math/pretext"/>
<xsl:variable name="docinfo" select="$melded-root/docinfo"/>
<xsl:variable name="document-root" select="$melded-root/*[not(self::docinfo)]"/>

<!-- Source analysis -->

<!-- We need to determine "how deep" the division hierarchy goes, so       -->
<!-- we probe for depths of four and five.  Note how specialized           -->
<!-- divisions result in additional depth beyond traditional divisions.    -->
<!-- (exercises|worksheet|handout|reading-questions|solutions|references|glossary) -->

<xsl:variable name="b-has-level-four" select="boolean(
      $document-root//subsubsection
    | $document-root//subsection/exercises
    | $document-root//subsection/worksheet
    | $document-root//subsection/handout
    | $document-root//subsection/reading-questions
    | $document-root//subsection/solutions
    | $document-root//subsection/references
    | $document-root//subsection/glossary)"/>

<xsl:variable name="b-has-level-five" select="boolean(
      $document-root//subsubsection/exercises
    | $document-root//subsubsection/worksheet
    | $document-root//subsubsection/handout
    | $document-root//subsubsection/reading-questions
    | $document-root//subsubsection/solutions
    | $document-root//subsubsection/references
    | $document-root//subsubsection/glossary)"/>

<!-- And anything less -->
<xsl:variable name="b-has-level-three-or-less" select="not($b-has-level-four) and not($b-has-level-five)"/>

<!-- ###################### -->
<!-- Conversion to Segments -->
<!-- ###################### -->

<!-- A "segment" is a chunk of text that begins on a new line and finishes  -->
<!-- with a partial line followed by a newline, ready for another segment.  -->
<!-- Various properties, akin to the main tools of braille formatting,      -->
<!-- affect how it is formatted into a BRF.  The XSL analyzes the nature of -->
<!-- the text and its surrounding from preTeXt markup, so then Python gets  -->
<!-- something that just describes how it should be formatted.              -->
<!--                                                                        -->
<!-- This documents much of the transition from PreTeXt XML to an XML meant -->
<!-- only for Python text processing.                                       -->
<!--                                                                        -->
<!-- Here we do not write anything when a default is correct, and then      -->
<!-- Python (lxml) will interpret a "missing" attribute as the default,     -->
<!-- and create something of the correct datatype for Python.               -->
<!--                                                                        -->
<!--     @newpage - default: no, else yes                                   -->
<!--     @centered - default: no, else yes                                  -->
<!--     @breakable - default: yes, else no                                 -->
<!--     @indentation - default: 0, else positive integer                   -->
<!--     @runover - default: 0, else positive integer                       -->
<!--     @lines-before - default: 0, else positive integer                  -->
<!--     @lines-after - default: 0, else positive integer                   -->
<!--     @lines-following - default: 0, else positive integer               -->

<!-- This is the main event, hidden within the formulation of a  -->
<!-- variable holding an RTF.  This is formed by the totality of -->
<!-- non-modal templates.  It will be converted into a node set, -->
<!-- for a post-processing step to incorporate "runin"           -->
<!-- title/heading elements into a subsequent segment.           -->
<xsl:variable name="segmented-rtf">
    <xsl:call-template name="warning-unimplemented"/>
    <xsl:call-template name="missing-warning"/>
    <xsl:apply-templates select="$melded-root"/>
</xsl:variable>

<!-- And we sneak in a warning that this conversion is underway, but not complete. -->
<xsl:template name="warning-unimplemented">
    <xsl:message>PTX:INFO: Some PreTeXt elements lack full implementation in the braille conversion.</xsl:message>
    <xsl:message>PTX:INFO: Smaller items will simply be missing from your output.</xsl:message>
    <xsl:message>PTX:INFO: Larger items may have all-caps placeholders in your output.</xsl:message>
    <xsl:message>PTX:INFO: These will all be reported as "Overlooked" in the log.</xsl:message>
    <xsl:message>PTX:INFO: Please report the complete list in the PreTeXt support forum,</xsl:message>
    <xsl:message>PTX:INFO: so we can prioritize making the output for your project complete.</xsl:message>
</xsl:template>

<!-- The entry template "waits" for the "$math-meld-rtf" and    -->
<!-- "$segmented-rtf" global variables to form, then the actual -->
<!-- output comes from two post-processing passes: the modal    -->
<!-- "meld-runin" templates absorb run-in titles into their     -->
<!-- segments, and then the modal "flatten-runs" templates      -->
<!-- dissolve nested font-change markup into a flat sequence    -->
<!-- of "run" elements bearing composite "@typeform" values.    -->
<xsl:template match="/">
    <xsl:variable name="melded-runin-rtf">
        <xsl:apply-templates select="exsl:node-set($segmented-rtf)/brf" mode="meld-runin"/>
    </xsl:variable>
    <xsl:apply-templates select="exsl:node-set($melded-runin-rtf)/brf" mode="flatten-runs"/>
</xsl:template>

<!-- ############################ -->
<!-- Flatten Font Changes to Runs -->
<!-- ############################ -->

<!-- Font-change markup ("italic", "bold", "code") arrives from the -->
<!-- earlier pass as elements, which may nest ("italic" containing  -->
<!-- "code", say).  A formatter wants a flat sequence, so each text -->
<!-- node becomes a "run" element whose "@typeform" records every   -->
<!-- font change in effect, as space-separated tokens.  Text with   -->
<!-- no font change rides along bare.  The font-change elements     -->
<!-- themselves evaporate.  Mathematics ("math") is already braille -->
<!-- cells and is preserved whole, its interior untouched.          -->

<!-- Dissolve, children continue -->
<xsl:template match="italic|bold|code" mode="flatten-runs">
    <xsl:apply-templates select="node()" mode="flatten-runs"/>
</xsl:template>

<!-- Mathematics is opaque, xerox entirely -->
<xsl:template match="math" mode="flatten-runs">
    <xsl:copy-of select="."/>
</xsl:template>

<!-- Text nodes inside a segment (or a converted run-in title)  -->
<!-- either ride bare (no font change) or become a "run".  The  -->
<!-- ancestor axis sees the font-change elements because they   -->
<!-- are still present in the tree under examination.           -->
<xsl:template match="text()" mode="flatten-runs">
    <xsl:variable name="typeform">
        <xsl:if test="ancestor::italic">
            <xsl:text>italic </xsl:text>
        </xsl:if>
        <xsl:if test="ancestor::bold">
            <xsl:text>bold </xsl:text>
        </xsl:if>
        <xsl:if test="ancestor::code">
            <xsl:text>code </xsl:text>
        </xsl:if>
    </xsl:variable>
    <xsl:choose>
        <xsl:when test="$typeform = ''">
            <xsl:value-of select="."/>
        </xsl:when>
        <xsl:otherwise>
            <run>
                <xsl:attribute name="typeform">
                    <xsl:value-of select="normalize-space($typeform)"/>
                </xsl:attribute>
                <xsl:value-of select="."/>
            </run>
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>

<!-- Xerox machine.  Elements and attributes only: text nodes have -->
<!-- their own template above, and it must win the match.          -->
<xsl:template match="*|@*" mode="flatten-runs">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()" mode="flatten-runs"/>
    </xsl:copy>
</xsl:template>

<!-- Process segments here, looking for run-in titles/headings -->
<xsl:template match="segment" mode="meld-runin">
    <!-- Look for "run-in" material just prior: the whole maximal   -->
    <!-- chain of consecutive "runin" siblings whose first          -->
    <!-- following non-"runin" sibling is this very segment.  Each  -->
    <!-- melds in, in order, with its separator.  Chains occur      -->
    <!-- routinely: an exercise, or a list item, may begin with a   -->
    <!-- nested list, stacking a marker for every level.            -->
    <xsl:variable name="runin-chain" select="preceding-sibling::runin[generate-id(following-sibling::*[not(self::runin)][1]) = generate-id(current())]"/>
    <xsl:copy>
        <xsl:apply-templates select="@*" mode="meld-runin"/>
        <!-- the chain's first runin positions the merged segment -->
        <xsl:apply-templates select="$runin-chain[1]/@indentation|$runin-chain[1]/@lines-before" mode="meld-runin"/>
        <xsl:for-each select="$runin-chain">
            <xsl:apply-templates select="node()" mode="meld-runin"/>
            <xsl:value-of select="@separator"/>
        </xsl:for-each>
        <xsl:apply-templates select="node()" mode="meld-runin"/>
    </xsl:copy>
</xsl:template>

<!-- A "runin" whose chain ends at a "segment" has been absorbed   -->
<!-- above; it must not persist.  A "runin" whose chain does NOT   -->
<!-- end at a segment (a block comes next, or nothing does) has no -->
<!-- host to meld into, so it becomes a segment of its own rather  -->
<!-- than disappear: content is never dropped silently.            -->
<xsl:template match="runin" mode="meld-runin">
    <xsl:choose>
        <xsl:when test="following-sibling::*[not(self::runin)][1][self::segment]">
            <!-- absorbed by that segment -->
        </xsl:when>
        <xsl:otherwise>
            <segment>
                <xsl:apply-templates select="@*|node()" mode="meld-runin"/>
            </segment>
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>

<!-- Xerox machine -->
<xsl:template match="@*|node()" mode="meld-runin">
    <xsl:copy>
        <xsl:apply-templates select="@*|node()" mode="meld-runin"/>
    </xsl:copy>
</xsl:template>

<!-- with /, so a plain generator can match others -->
<xsl:template match="/pretext">
    <!-- Need an overall container   -->
    <!-- Maybe copy a language code? -->
    <brf>
        <!-- Record how braille cells are represented ("early" is  -->
        <!-- BRF ASCII symbols, "late" is Unicode braille cells)   -->
        <!-- so the renderer can react to mathematics accordingly. -->
        <xsl:attribute name="brf-symbols">
            <xsl:value-of select="$brf-symbols"/>
        </xsl:attribute>
        <!-- Page geometry, from the publication file (or the      -->
        <!-- defaults), for the renderer: cells in a line, lines   -->
        <!-- on an embossed page.                                  -->
        <xsl:attribute name="page-width">
            <xsl:value-of select="$braille-page-width"/>
        </xsl:attribute>
        <xsl:attribute name="page-height">
            <xsl:value-of select="$braille-page-height"/>
        </xsl:attribute>
        <!-- centered heading on line 1 -->
        <segment centered="yes" lines-after="1">Transcriber Notes</segment>
        <!-- Literal text for each note, control whitespace,  -->
        <!-- etc here, since it will not be handled otherwise -->
        <xsl:if test="//c">
        <!-- See "c" template for explanation -->
            <segment indentation="2">
                <xsl:text>Literal, or verbatim, computer code used in sentences is indicated by a set of transcriber-defined emphasis given by the following indicators, which all begin with the two cells dot-4 and dot-3456.  Single letter: 4-3456-23.  Begin, end word: 4-3456-2, 4-3456-3.  Begin, end phrase: 4-3456-2356, 4-3456-3.</xsl:text>
            </segment>
        </xsl:if>
        <!--  -->
        <xsl:if test="//image">
            <segment indentation="2">
                <xsl:text>Images are replaced by authors' descriptions, and then in an embossed version, a full (numbered) page comes next, which can be manually replaced by a tactile version of the image.</xsl:text>
            </segment>
        </xsl:if>
        <!--  -->
        <xsl:if test="//sidebyside">
            <segment indentation="2">
                <xsl:text>A "side-by-side" is a horizontal layout of document elements.  The components of a side-by-side are called "panels".  Typically panels are images or figures, but can also be items like program listings, tables, or paragraphs.  For braille, we let each panel use the full width of the page, so we announce the start, indicating the total number of panels.  Then we preface each panel with its number in the sequence.  Finally we announce the end because it may be hard to distinguish a final panel from the ensuing text.</xsl:text>
            </segment>
        </xsl:if>
        <!--  -->
        <!-- [BANA-2016, 8.6.2(b)] bullet symbols used in lists are -->
        <!-- listed in a transcriber's note                          -->
        <xsl:if test="//ul">
            <segment indentation="2">
                <xsl:text>Items of unordered lists retain their print markers, each followed by a period.  The symbols in use are: bullet (dots 456, 256), circle (dots 1246 and a grade one indicator, 123456), and square (dots 456, 1246, 3456, 145).</xsl:text>
            </segment>
        </xsl:if>
        <!--  -->
        <!-- automatically infers we have a note already for "sidebyside" -->
        <xsl:if test="//sbsgroup">
            <segment indentation="2">
                <xsl:text>A "side-by-side group" is a sequence down the page of "side-by-side" (see previous note).  We announce the start with the number of side-by-side in the group to expect, and let the beginning and ending notes for each side-by-side delineate the sequence.</xsl:text>
            </segment>
        </xsl:if>
        <!-- mention how "tabular" are implenented and suggest possible improvements-->
        <xsl:if test="//tabular">
            <segment indentation="2">
                <xsl:text>Tabular material is always implemented using a "linear table format".  A human transcriber may be able to improve small tables, or larger tables that could use multiple pages when embossed, by using a different format.</xsl:text>
            </segment>
        </xsl:if>
        <!-- process segments and blocks of "brf" -->
        <xsl:apply-templates select="*"/>
    </brf>
</xsl:template>

<!-- ######### -->
<!-- Divisions -->
<!-- ######### -->

<!-- [BANA, 2016] 4.2.1 -->
<!-- As a general rule, centered headings are used to represent     -->
<!-- the print headings of major sections of the text, and cell-5   -->
<!-- and cell-7 headings are used to represent the print headings   -->
<!-- for subsections shown within major sections. When there are    -->
<!-- more than three distinct heading levels in print, cell-7       -->
<!-- headings are applied only to the lowest hierarchy level; the   -->
<!-- use of centered headings is extended to one or more subsection -->
<!-- levels as necessary.                                           -->

<!-- Braille division headings are centered, indented 4 cells ("cell-5"),   -->
<!-- or indented 6 cells ("cell-7"), along with blank lines possibly        -->
<!-- before and after.  Cell-7 is always terminal and is only used at one   -->
<!-- level.   To "fill" when there are more than three levels, centered     -->
<!-- headings get extended.  At the chapter level of a book, we start at    -->
<!-- the top of a page, which somewhat distinguishes the centered style     -->
<!-- of a chapter.  From PreTeXt, division numbers (if used) are            -->
<!-- unambiguous indicators of levels.                                      -->
<!--                                                                        -->
<!-- Level                        book                      article         -->
<!-- 1 chapter           center  center  center                             -->
<!-- 2 section           cell-5  center  center      center  center  center -->
<!-- 3 subsection        cell-7  cell-5  center      cell-7  cell-5  center -->
<!-- 4 subsubsection             cell-7  cell-5              cell-7  cell-5 -->
<!-- 5 (specialized)                     cell-7                      cell-7 -->

<!-- Divisions apparent in a rendered BRF. -->
<xsl:template match="chapter|appendix|index[index-list]|index-part|preface|acknowledgement|biography|foreword|dedication|colophon|section|subsection|subsubsection|slide|exercises|worksheet|handout|reading-questions|solutions|references|glossary">

    <!-- Determine: newpage, centered, cell5, cell7 -->
    <xsl:variable name="heading-style">
        <xsl:apply-templates select="." mode="heading-style"/>
    </xsl:variable>

    <segment breakable="no" lines-following="1">
        <!-- various attributes are fixed (above) or -->
        <!-- vary according to the heading-style     -->
        <xsl:attribute name="newpage">
            <xsl:choose>
                <xsl:when test="$heading-style = 'newpage'">
                    <xsl:text>yes</xsl:text>
                </xsl:when>
                <xsl:otherwise>
                    <!-- Explicit defaults for Python, partially to get types right -->
                    <xsl:text>no</xsl:text>
                </xsl:otherwise>
            </xsl:choose>
        </xsl:attribute>
        <!--  -->
        <xsl:attribute name="centered">
            <xsl:choose>
                <xsl:when test="($heading-style = 'newpage') or ($heading-style = 'centered')">
                    <xsl:text>yes</xsl:text>
                </xsl:when>
                <!-- Explicit defaults for Python, partially to get types right -->
                <xsl:otherwise>
                    <xsl:text>no</xsl:text>
                </xsl:otherwise>
            </xsl:choose>
        </xsl:attribute>
        <!--  -->
        <xsl:variable name="indentation">
            <xsl:choose>
                <xsl:when test="$heading-style = 'cell5'">
                    <xsl:text>4</xsl:text>
                </xsl:when>
                <xsl:when test="$heading-style = 'cell7'">
                    <xsl:text>6</xsl:text>
                </xsl:when>
                <!-- Explicit defaults for Python, partially to get types right -->
                <xsl:otherwise>
                    <xsl:text>0</xsl:text>
                </xsl:otherwise>
            </xsl:choose>
        </xsl:variable>
        <!--  -->
        <xsl:attribute name="indentation">
            <xsl:value-of select="$indentation"/>
        </xsl:attribute>
        <!--  -->
        <xsl:attribute name="runover">
            <xsl:value-of select="$indentation"/>
        </xsl:attribute>
        <!-- Indicate a "line-before" whenever necessary for an     -->
        <!-- electronic version.  Page formatting for an embossed   -->
        <!-- version will not include these at the start of a page. -->
        <xsl:attribute name="lines-before">
            <xsl:choose>
                <xsl:when test="$heading-style = 'newpage'">
                    <xsl:text>1</xsl:text>
                </xsl:when>
                <!-- [BANA 2016], 4.4.1                                           -->
                <!-- A centered heading is preceded and followed by a blank line. -->
                <xsl:when test="$heading-style = 'centered'">
                    <xsl:text>1</xsl:text>
                </xsl:when>
                <xsl:when test="$heading-style = 'cell5'">
                    <xsl:text>1</xsl:text>
                </xsl:when>
                <xsl:when test="$heading-style = 'cell7'">
                    <xsl:text>1</xsl:text>
                </xsl:when>
            </xsl:choose>
        </xsl:attribute>
        <!--  -->
        <xsl:attribute name="lines-after">
            <xsl:choose>
                <xsl:when test="$heading-style = 'newpage'">
                    <xsl:text>1</xsl:text>
                </xsl:when>
                <!-- [BANA 2016], 4.4.1                                           -->
                <!-- A centered heading is preceded and followed by a blank line. -->
                <xsl:when test="$heading-style = 'centered'">
                    <xsl:text>1</xsl:text>
                </xsl:when>
                <xsl:when test="$heading-style = 'cell5'">
                    <xsl:text>0</xsl:text>
                </xsl:when>
                <xsl:when test="$heading-style = 'cell7'">
                    <xsl:text>0</xsl:text>
                </xsl:when>
            </xsl:choose>
        </xsl:attribute>
        <!-- division headings go to the Table of Contents -->
        <xsl:attribute name="heading-id">
            <xsl:apply-templates select="." mode="unique-id"/>
        </xsl:attribute>
        <!-- TODO: record heading levels for indentation/runover in ToC -->
        <!--  -->
        <!-- Finally, the heading content itself -->
       <xsl:variable name="the-number">
            <xsl:apply-templates select="." mode="number"/>
        </xsl:variable>
        <xsl:if test="not($the-number = '')">
            <xsl:value-of select="$the-number"/>
            <xsl:text> </xsl:text>
        </xsl:if>
        <xsl:apply-templates select="." mode="title-full"/>
    </segment>
    <!-- end heading segment, recurse into the -->
    <!-- contents of the (structured) division -->
    <xsl:apply-templates select="*"/>
</xsl:template>

<!-- Overall document "types/classes", level 0/-1 -->
<!-- Normalize so that: "chapter" is always level 1, "section"  -->
<!-- is always level 2.  We do not ever consult these specific  -->
<!-- values for the document type/class, they are not imporant. -->
<!--  Also, the climb up the tree ends here.                    -->
<xsl:template match="book|article|slideshow|letter|memo" mode="braille-level">
    <xsl:choose>
        <!-- "book" with parts, make "part" level 0 -->
        <xsl:when test="$b-has-parts">
            <xsl:text>-1</xsl:text>
        </xsl:when>
        <xsl:otherwise>
            <xsl:text>0</xsl:text>
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>

<!-- Containiers, inherit from parent -->
<xsl:template match="frontmatter|backmatter" mode="braille-level">
    <xsl:apply-templates select="parent::*" mode="braille-level"/>
</xsl:template>

<!-- True divisions, +1 from parent -->
<xsl:template match="part|chapter|appendix|index[index-list]|index-part|preface|acknowledgement|biography|foreword|dedication|colophon|section|subsection|subsubsection|slide|exercises|worksheet|handout|reading-questions|solutions|references|glossary" mode="braille-level">
    <xsl:variable name="parent-level">
        <xsl:apply-templates select="parent::*" mode="braille-level"/>
    </xsl:variable>
    <xsl:value-of select="$parent-level + 1"/>
</xsl:template>

<!-- Divisions apparent in a BRF.  Four headings styles,       -->
<!-- which we use to "define" how headings are formatted.      -->
<!-- Specialized divisions can appear at many levels, but will -->
<!-- be formatted according to their level in the hierarchy.   -->
<!-- See table above for explanation of choices here.          -->
<xsl:template match="chapter|appendix|index[index-list]|index-part|preface|acknowledgement|biography|foreword|dedication|colophon|section|subsection|subsubsection|slide|exercises|worksheet|handout|reading-questions|solutions|references|glossary" mode="heading-style">
    <xsl:variable name="braille-level">
        <xsl:apply-templates select="." mode="braille-level"/>
    </xsl:variable>
    <xsl:choose>
        <!-- chapters (of books) -->
        <xsl:when test="$braille-level = 1">
            <xsl:text>newpage</xsl:text>
        </xsl:when>
        <!-- sections (of books or articles) -->
        <xsl:when test="$braille-level = 2">
            <xsl:choose>
                <xsl:when test="$b-has-level-three-or-less and $b-is-book">
                    <xsl:text>cell5</xsl:text>
                </xsl:when>
                <xsl:otherwise>
                    <xsl:text>centered</xsl:text>
                </xsl:otherwise>
            </xsl:choose>
        </xsl:when>
        <!--  -->
        <xsl:when test="$braille-level = 3">
            <xsl:choose>
                <xsl:when test="$b-has-level-five">
                    <xsl:text>centered</xsl:text>
                </xsl:when>
                <xsl:when test="$b-has-level-four">
                    <xsl:text>cell5</xsl:text>
                </xsl:when>
                <xsl:otherwise>
                    <xsl:text>cell7</xsl:text>
                </xsl:otherwise>
            </xsl:choose>
        </xsl:when>
        <!--  -->
        <xsl:when test="$braille-level = 4">
            <xsl:choose>
                <xsl:when test="$b-has-level-five">
                    <xsl:text>cell5</xsl:text>
                </xsl:when>
                <xsl:otherwise>
                    <xsl:text>cell7</xsl:text>
                </xsl:otherwise>
            </xsl:choose>
        </xsl:when>
        <!--  -->
        <xsl:when test="$braille-level = 5">
            <xsl:text>cell7</xsl:text>
         </xsl:when>
        <!--  -->
        <xsl:otherwise>
            <xsl:text>UNDEFINED</xsl:text>
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>

<!-- ###################### -->
<!-- Exceptional Containers -->
<!-- ###################### -->

<!-- A special division: "paragraphs" -->
<xsl:template match="paragraphs">
    <!-- Should be run-in with automatic space afterward -->
    <xsl:if test="title">
        <segment lines-before="1">
            <xsl:apply-templates select="." mode="title-full"/>
        </segment>
    </xsl:if>
    <xsl:apply-templates select="*"/>
</xsl:template>

<!-- Very lightweight, title is optional,    -->
<!-- and does not default to "SubExercises". -->
<xsl:template match="subexercises">
    <xsl:if test="title">
        <segment lines-before="1">
            <xsl:apply-templates select="." mode="title-full"/>
        </segment>
    </xsl:if>
    <xsl:apply-templates select="introduction"/>
    <xsl:apply-templates select="exercise|exercisegroup"/>
    <xsl:apply-templates select="conclusion"/>
</xsl:template>

<!-- An "exercisegroup" is very visual, so  -->
<!-- we delimit it with a transcriber note. -->
<xsl:template match="exercisegroup">
    <xsl:apply-templates select="." mode="transcriber-note">
        <xsl:with-param name="message">
            <xsl:text>An exercise group follows.  </xsl:text>
            <!-- optional, so with trailing space -->
            <xsl:if test="introduction">
                <xsl:text>It begins with an introduction.  </xsl:text>
            </xsl:if>
            <xsl:text>The exercises run from number </xsl:text>
            <xsl:apply-templates select="exercise[1]" mode="serial-number"/>
            <xsl:text> to number </xsl:text>
            <xsl:apply-templates select="exercise[last()]" mode="serial-number"/>
            <xsl:text>.</xsl:text>
            <!-- optional, so with leading space -->
            <xsl:if test="conclusion">
                <xsl:text>  It finishes with a conclusion.</xsl:text>
            </xsl:if>
        </xsl:with-param>
    </xsl:apply-templates>
    <!--  -->
    <xsl:apply-templates select="introduction"/>
    <xsl:apply-templates select="exercise"/>
    <xsl:apply-templates select="conclusion"/>
</xsl:template>


<!-- ###### -->
<!-- Blocks -->
<!-- ###### -->

<!-- "Blocks" are major components of PreTeXt output.  Typically  -->
<!-- numbered, titled, set-off, and sometimes with subsidiary     -->
<!-- pieces hanging off them.  For braille, they might not        -->
<!-- cross page boundaries, and may have box lines, etc.          -->
<!--                                                              -->
<!-- We handle the title as a heading of sorts, which might not   -->
<!-- cross a page boundary, and which might be "stuck" on a       -->
<!-- certain number of following lines.  See the discussion below -->
<!-- about titles.                                                -->

<!-- "Regular" blocks, including inline "exercise" (aka "Checkpoint") -->
<xsl:template match="&DEFINITION-LIKE;|&THEOREM-LIKE;|&AXIOM-LIKE;|&REMARK-LIKE;|&COMPUTATION-LIKE;|&ASIDE-LIKE;|&EXAMPLE-LIKE;|&PROJECT-LIKE;|&GOAL-LIKE;|&OPENPROBLEM-LIKE;|exercise[&INLINE-EXERCISE-FILTER;]|assemblage">
    <block breakable="no" box="standard" lines-before="1" lines-after="1">
        <xsl:apply-templates select="." mode="block-title"/>
        <xsl:apply-templates select="*[not(self::title)]"/>
    </block>
</xsl:template>

<!-- "Other" exercises (in "exercises" divisions, in "reading questions", -->
<!-- in worksheets) are not as prominent and have run-in titles           -->
<xsl:template match="exercise[not(&INLINE-EXERCISE-FILTER;)]">
    <xsl:apply-templates select="." mode="block-title"/>
    <xsl:apply-templates select="*[not(self::title)]"/>
</xsl:template>

<!-- The appendages are not yet blocks, they live inside blocks           -->
<!-- NOTE: if these become contained blocks, that is a structural change  -->
<!-- that will require changes in the Python lxml which assumes otherwise -->
<xsl:template match="&PROOF-LIKE;|&SOLUTION-LIKE;|&DISCUSSION-LIKE;">
    <xsl:apply-templates select="." mode="block-title"/>
    <xsl:apply-templates select="*[not(self::title)]"/>
</xsl:template>

<!-- A "case" is a further division of a PROOF-LIKE -->
<xsl:template match="case">
    <runin indentation="2" separator="&#x20;">
        <xsl:apply-templates select="." mode="title-full"/>
    </runin>
    <xsl:apply-templates select="*"/>
</xsl:template>

<!-- Titles of blocks can be an entire "segment" if they finish with a  -->
<!-- newline.  Other titles are "runin" and are consolidated in a final -->
<!-- post-processing step.                                              -->

<xsl:template match="&DEFINITION-LIKE;|&THEOREM-LIKE;|&AXIOM-LIKE;|&REMARK-LIKE;|&COMPUTATION-LIKE;|&ASIDE-LIKE;|&EXAMPLE-LIKE;|&PROJECT-LIKE;|&OPENPROBLEM-LIKE;|exercise[&INLINE-EXERCISE-FILTER;]" mode="block-title">
    <segment lines-before="0">
        <!--  -->
        <xsl:apply-templates select="." mode="type-name"/>
        <!--  -->
        <xsl:variable name="the-number">
            <xsl:apply-templates select="." mode="number"/>
        </xsl:variable>
        <xsl:if test="not($the-number = '')">
            <xsl:text> </xsl:text>
            <xsl:value-of select="$the-number"/>
        </xsl:if>
        <!--  -->
        <xsl:if test="title">
            <xsl:text> </xsl:text>
            <xsl:apply-templates select="." mode="title-full"/>
        </xsl:if>
        <!--  -->
    </segment>
</xsl:template>

<!-- An assemblage is not numbered, it is just a box.  The title is optional. -->
<xsl:template match="assemblage" mode="block-title">
    <xsl:if test="title">
        <segment lines-before="0">
        <xsl:apply-templates select="." mode="title-full"/>
        </segment>
    </xsl:if>
</xsl:template>

<!-- Should be run-in with automatic space afterward -->
<!-- There may be multiple proofs, but we do not number them at birth, -->
<!-- the number only gets used in a cross-reference.  Maybe standalone -->
<!-- is different??                                                    -->
<!-- TENTATIVE: DISCUSSION-LIKE may be identical                       -->
<xsl:template match="&PROOF-LIKE;|&DISCUSSION-LIKE;" mode="block-title">
        <runin indentation="0" lines-before="1" separator="&#x20;">
        <!--  -->
        <xsl:apply-templates select="." mode="type-name"/>
        <xsl:text>.</xsl:text>
        <!--  -->
        <xsl:if test="title">
            <xsl:text> </xsl:text>
            <xsl:apply-templates select="." mode="title-full"/>
        </xsl:if>
        <!--  -->
    </runin>
</xsl:template>

<!-- Should be run-in with automatic space afterward -->
<xsl:template match="exercise[not(&INLINE-EXERCISE-FILTER;)]" mode="block-title">
    <runin indentation="0" lines-before="1" separator="&#x20;">
        <xsl:apply-templates select="." mode="serial-number"/>
        <xsl:text>.</xsl:text>
        <!--  -->
        <xsl:if test="title">
            <xsl:text> (</xsl:text>
            <xsl:apply-templates select="." mode="title-full"/>
            <xsl:text>)</xsl:text>
        </xsl:if>
        <!--  -->
    </runin>
</xsl:template>

<!-- Should be run-in with automatic space afterward -->
<xsl:template match="&SOLUTION-LIKE;" mode="block-title">
    <runin indentation="0" lines-before="1" separator="&#x20;">
        <!--  -->
        <xsl:apply-templates select="." mode="type-name"/>
        <!--  -->
        <xsl:variable name="the-number">
             <xsl:apply-templates select="." mode="non-singleton-number"/>
        </xsl:variable>
        <xsl:if test="not($the-number = '')">
            <xsl:text> </xsl:text>
            <xsl:value-of select="$the-number"/>
        </xsl:if>
        <xsl:text>.</xsl:text>
        <!--  -->
        <xsl:if test="title">
            <xsl:text> (</xsl:text>
            <xsl:apply-templates select="." mode="title-full"/>
            <xsl:text>)</xsl:text>
        </xsl:if>
        <!--  -->
    </runin>
</xsl:template>

<!-- Print is "Type: Title", no number, since there is only one per     -->
<!-- division and the number is implicitly that of the parent division. -->
<xsl:template match="&GOAL-LIKE;" mode="block-title">
    <segment lines-before="0">
        <!--  -->
        <xsl:apply-templates select="." mode="type-name"/>
        <!--  -->
        <xsl:if test="title">
            <xsl:text>: </xsl:text>
            <xsl:apply-templates select="." mode="title-full"/>
        </xsl:if>
        <!--  -->
    </segment>
</xsl:template>


<!-- ########### -->
<!-- FIGURE-LIKE -->
<!-- ########### -->

<!-- [BANA, 2016] 6.2.2 -->
<!-- 7-5 margins for captions of "Illustrative Materials" -->
<!-- We generalize to titles of "table" and "list" blocks -->

<!-- [BANA, 2016] 6.2.2(e) -->
<!-- When both a print caption and a transcriber-generated description    -->
<!-- are needed, begin the description (enclosed in transcriber's note    -->
<!-- indicators) on the line following the caption.                       -->
<!-- Figures are treated different for the case where their contents are  -->
<!-- images (thus requiring a tactile graphic page to follow the figure). -->
<xsl:template match="figure[image]">
    <block breakable="no" box="standard" lines-before="1" lines-after="1">
        <segment indentation="6" runover="4">
            <xsl:apply-templates select="." mode="block-title"/>
        </segment>
        <xsl:apply-templates select="*[not(self::image)]"/>
        <xsl:apply-templates select="image" mode="braille-representation"/>
    </block>
    <!-- Form a page to be replaced by tactile version -->
    <block ownpage="yes">
        <xsl:apply-templates select="." mode="transcriber-note">
            <xsl:with-param name="message">
                <xsl:text>Replace this page with </xsl:text>
                <xsl:apply-templates select="." mode="block-title"/>
            </xsl:with-param>
        </xsl:apply-templates>
    </block>
</xsl:template>

<!-- Other FIGURE-LIKE can be handled together -->
<xsl:template match="&FIGURE-LIKE;">
    <block breakable="no" box="standard" lines-before="1" lines-after="1">
        <segment indentation="6" runover="4">
            <!-- [BANA, 2016, 11.17.1a] "Leave a blank line after the title." -->
            <!-- Guidance for tables, we mimic for PTX "list" block.          -->
            <xsl:if test="self::table or self::list">
                <xsl:attribute name="lines-after">
                    <xsl:text>1</xsl:text>
                </xsl:attribute>
            </xsl:if>
            <xsl:apply-templates select="." mode="block-title"/>
        </segment>
        <xsl:apply-templates select="*"/>
    </block>
</xsl:template>

<!-- Caption/title, with label, number, etc.  "caption" and -->
<!-- "title" elements are metadata, killed in -common,      -->
<!-- obtained as needed via modal templates.                -->
<xsl:template match="&FIGURE-LIKE;" mode="block-title">
    <xsl:apply-templates select="." mode="type-name"/>
    <!--  -->
    <xsl:variable name="the-number">
         <xsl:apply-templates select="." mode="number"/>
    </xsl:variable>
    <xsl:if test="not($the-number = '')">
        <xsl:text> </xsl:text>
        <xsl:value-of select="$the-number"/>
    </xsl:if>
    <xsl:text>. </xsl:text>
    <xsl:choose>
        <xsl:when test="self::figure">
            <xsl:apply-templates select="." mode="caption-full"/>
        </xsl:when>
        <xsl:when test="self::table|self::list|self::listing">
            <xsl:apply-templates select="." mode="title-full"/>
        </xsl:when>
    </xsl:choose>
</xsl:template>

<!-- ###### -->
<!-- Images -->
<!-- ###### -->

<!-- A bare image becomes a transcriber note with a small amount -->
<!-- of identification, and then generates a replacement page.   -->
<xsl:template match="image">
    <!-- A "segment" with the ID of the image to identify it, -->
    <xsl:apply-templates select="." mode="transcriber-note">
        <xsl:with-param name="message">
            <xsl:apply-templates select="." mode="block-title"/>
        </xsl:with-param>
    </xsl:apply-templates>
    <!-- Then the author's descriptions -->
    <xsl:apply-templates select="." mode="braille-representation"/>
    <!-- Form a page to be replaced by tactile version -->
    <block ownpage="yes">
        <xsl:apply-templates select="." mode="transcriber-note">
            <xsl:with-param name="message">
                <xsl:text>Replace this page with </xsl:text>
                <xsl:apply-templates select="." mode="block-title"/>
            </xsl:with-param>
        </xsl:apply-templates>
    </block>
</xsl:template>

<!-- A transcriber note replacing an image when included -->
<!-- in some other (identifying) structure.              -->
<xsl:template match="image" mode="braille-representation">
    <!-- A "segment" with the author's "shortdescription" -->
    <xsl:if test="shortdescription">
        <xsl:apply-templates select="." mode="transcriber-note">
            <xsl:with-param name="message">
                <xsl:apply-templates select="shortdescription"/>
            </xsl:with-param>
        </xsl:apply-templates>
    </xsl:if>
</xsl:template>

<!-- Not really a title, but a repeated identification of an image  -->
<!-- to coordinate text and manually inserted tactile versions.     -->
<xsl:template match="image" mode="block-title">
    <xsl:text>Image: </xsl:text>
    <xsl:apply-templates select="." mode="unique-id"/>
    <xsl:text>.</xsl:text>
</xsl:template>

<!-- ############ -->
<!-- Side-by-Side -->
<!-- ############ -->

<!-- We delimit the panels of a "sidebyside" with an introductory        -->
<!-- transcriber note and a concluding note.  Each panel is preceded     -->
<!-- by a very short transcriber note giving its number in the sequence. -->
<!-- An "sbsgroup" only announces its start, but each "sidebyside"       -->
<!-- introduction provides the number within the group.                  -->
<!--                                                                     -->
<!-- Otherwise, a "sidebyside" is just "linearized" and strung out down  -->
<!-- pages, rather than across, since horizontal real estate is limited  -->
<!-- and images are going full (own) page.                               -->
<!-- From discussion with Michael Cantino and Al Maneki, 2023-03-30      -->
<!--                                                                     -->
<!-- This is the same linear composition as the text conversion (no      -->
<!-- horizontal layout, so the -common machinery is unused), but         -->
<!-- with braille-idiomatic transcriber notes, so the two                -->
<!-- conversions share the design, not the code.                         -->

<xsl:template match="sidebyside">
    <xsl:variable name="npanels" select="count(*)"/>
    <!-- Intro -->
    <!-- At a 40-character width, this will fit on one line with -->
    <!-- two cells to spare when the count is single-digit.      -->
    <xsl:apply-templates select="." mode="transcriber-note">
        <xsl:with-param name="message">
            <xsl:text>side-by-side: </xsl:text>
            <!-- panels are simply child elements -->
            <xsl:value-of select="$npanels"/>
            <xsl:text> panels</xsl:text>
        </xsl:with-param>
    </xsl:apply-templates>
    <!-- Panels -->
    <xsl:for-each select="*">
        <xsl:variable name="number" select="count(preceding-sibling::*) + 1"/>
        <xsl:apply-templates select="." mode="transcriber-note">
            <xsl:with-param name="message">
                <xsl:text>panel: </xsl:text>
                <xsl:value-of select="$number"/>
                <xsl:text>/</xsl:text>
                <xsl:value-of select="$npanels"/>
            </xsl:with-param>
        </xsl:apply-templates>
        <!-- context switch, so self -->
        <xsl:apply-templates select="."/>
    </xsl:for-each>
    <!-- Outro -->
    <!-- This message mimics the format of the opening note -->
    <xsl:apply-templates select="." mode="transcriber-note">
        <xsl:with-param name="message">
            <xsl:text>side-by-side: end</xsl:text>
        </xsl:with-param>
    </xsl:apply-templates>
</xsl:template>

<xsl:template match="sbsgroup">
    <xsl:variable name="nsbs" select="count(sidebyside)"/>
    <xsl:apply-templates select="." mode="transcriber-note">
        <xsl:with-param name="message">
            <xsl:text>side-by-side group: </xsl:text>
            <xsl:value-of select="$nsbs"/>
            <xsl:text> sbs</xsl:text>
        </xsl:with-param>
    </xsl:apply-templates>
    <xsl:apply-templates select="*"/>
</xsl:template>

<!-- A "stack" is strictly a side-by-side panel and we just -->
<!-- process its children.  No need to get carried away for -->
<!-- braille, and maybe an "apply-imports" (or nothing at   -->
<!-- all) is the right thing to do.                         -->
<xsl:template match="stack">
    <xsl:apply-templates select="*"/>
</xsl:template>

<!-- ##### -->
<!-- Lists -->
<!-- ##### -->

<!-- Lists are containers full of list items.  The container's -->
<!-- one responsibility: [BANA-2016, 8.3.2(a)] a list is        -->
<!-- preceded and followed by a blank line.  That means the     -->
<!-- OUTERMOST list; a nested list runs on without a break.     -->
<!-- (An empty segment demanding a line before it is the idiom  -->
<!-- for one blank line, suppressed at the top of a page.)      -->
<xsl:template match="ul|ol|dl">
    <xsl:variable name="b-outermost" select="not(ancestor::ol or ancestor::ul or ancestor::dl)"/>
    <xsl:if test="$b-outermost">
        <segment lines-before="1"/>
    </xsl:if>
    <xsl:apply-templates select="li"/>
    <xsl:if test="$b-outermost">
        <segment lines-before="1"/>
    </xsl:if>
</xsl:template>

<xsl:template match="li">
    <!-- [BANA-2016, 8.3.1] a simple list has 1-3 margins           -->
    <!-- [BANA-2016, 8.5.1(b)] each nested level begins two cells   -->
    <!-- to the right of the previous level, and ALL runovers begin -->
    <!-- two cells to the right of the farthest indented level: one -->
    <!-- level is 1-3; two levels are 1-5, 3-5; three levels are    -->
    <!-- 1-7, 3-7, 5-7.  In the preprint's 0-based attributes:      -->
    <!-- level k of an n-level list has indentation 2(k-1), and     -->
    <!-- every segment of the list has runover 2n.                  -->
    <!-- The level of this item, and the deepest level anywhere in  -->
    <!-- the outermost list containing it.  (A list separated from  -->
    <!-- an enclosing list by other structure still counts every    -->
    <!-- list ancestor, deliberately: its margins nest visibly.)    -->
    <xsl:variable name="level" select="count(ancestor::ol | ancestor::ul | ancestor::dl)"/>
    <xsl:variable name="outermost-list" select="ancestor::*[self::ol or self::ul or self::dl][last()]"/>
    <xsl:variable name="list-depth">
        <xsl:for-each select="$outermost-list//li">
            <xsl:sort select="count(ancestor::ol | ancestor::ul | ancestor::dl)" data-type="number" order="descending"/>
            <xsl:if test="position() = 1">
                <xsl:value-of select="count(ancestor::ol | ancestor::ul | ancestor::dl)"/>
            </xsl:if>
        </xsl:for-each>
    </xsl:variable>
    <xsl:variable name="list-runover" select="2 * $list-depth"/>
    <!-- Marker as a "runin" element -->
    <runin indentation="{2 * ($level - 1)}" separator="&#x20;">
        <xsl:choose>
            <xsl:when test="parent::ol">
                <xsl:apply-templates select="." mode="item-number"/>
                <xsl:text>.</xsl:text>
            </xsl:when>
            <xsl:when test="parent::ul">
                <xsl:apply-templates select="." mode="unicode-list-marker"/>
                <xsl:text>.</xsl:text>
            </xsl:when>
            <xsl:when test="parent::dl">
                <xsl:apply-templates select="." mode="title-full"/>
            </xsl:when>
        </xsl:choose>
    </runin>
    <xsl:choose>
        <!-- A structured list item carries paragraphs, or other   -->
        <!-- block-shaped material, all of which make segments (or  -->
        <!-- whole blocks) of their own.  The test mirrors the      -->
        <!-- schema exactly: an "li" may hold BlockStatement, which -->
        <!-- is BlockText (paragraph, blockquote, preformatted,     -->
        <!-- image, video, audio, program, console, tabular), the   -->
        <!-- figure family (figure, table, listing, list), aside,   -->
        <!-- side-by-sides, and Sage cells.  Displayed items that   -->
        <!-- can live within a paragraph (nested lists, display     -->
        <!-- mathematics) are deliberately NOT in this test: mixed  -->
        <!-- content holds them, and the paragraph machinery        -->
        <!-- splits them out correctly.                             -->
        <xsl:when test="p or blockquote or pre or image or video or audio or program or console or tabular or figure or table or listing or list or aside or sidebyside or sbsgroup or sage">
            <xsl:apply-templates select="node()">
                <xsl:with-param name="list-runover" select="$list-runover"/>
            </xsl:apply-templates>
        </xsl:when>
        <!-- An unstructured list item is a run of sentences,      -->
        <!-- exactly the content of a paragraph.  But with no      -->
        <!-- "p" there is no template to make a segment of it, and -->
        <!-- unanchored content is lost.  So manufacture the       -->
        <!-- missing paragraph around a copy of the content, and   -->
        <!-- process that: the ordinary paragraph templates then   -->
        <!-- apply, including the splitting of displayed items     -->
        <!-- (display mathematics, a nested list) into siblings.   -->
        <!--                                                       -->
        <!-- TODO: the project direction is to manufacture such    -->
        <!-- missing wrappers ("p", "statement") once, during      -->
        <!-- assembly, marked with a "pi:" attribute, so authors   -->
        <!-- keep their freedom while conversions see uniform      -->
        <!-- structure.  When that arrives, this local device      -->
        <!-- evaporates: the manufactured "p" is a real one here,  -->
        <!-- and its flag guides any special list treatment.       -->
        <xsl:otherwise>
            <xsl:variable name="virtual-paragraph-rtf">
                <p>
                    <xsl:copy-of select="node()"/>
                </p>
            </xsl:variable>
            <xsl:apply-templates select="exsl:node-set($virtual-paragraph-rtf)/p">
                <xsl:with-param name="list-runover" select="$list-runover"/>
            </xsl:apply-templates>
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>

<xsl:template match="ul/li" mode="unicode-list-marker">
    <xsl:variable name="format-code" select="parent::ul/@pi:format-code"/>
    <!-- The list label.  The file  en-ueb-chardefs.uti        -->
    <!-- associates these Unicode values with the indicated    -->
    <!-- dot patterns.  This jibes with [BANA-2016, 8.6.2],    -->
    <!-- which says the open circle needs a Grade 1 indicator. -->
    <!-- The file  en-ueb-g2.ctb  lists  x25cb  and  x24a0  as -->
    <!-- both being "contraction" and so needing a             -->
    <!-- Grade 1 indicator.                                    -->
    <xsl:choose>
        <!-- Unicode Character 'BULLET' (U+2022)       -->
        <!-- Dot pattern: 456-256                      -->
        <xsl:when test="$format-code = 'disc'">
            <xsl:text>&#x2022; </xsl:text>
        </xsl:when>
        <!-- Unicode Character 'WHITE CIRCLE' (U+25CB) -->
        <!-- Dot pattern: 1246-123456                  -->
        <xsl:when test="$format-code = 'circle'">
            <xsl:text>&#x25cb; </xsl:text>
        </xsl:when>
        <!-- Unicode Character 'BLACK SQUARE' (U+25A0) -->
        <!-- Dot pattern: 456-1246-3456-145            -->
        <xsl:when test="$format-code = 'square'">
            <xsl:text>&#x25a0; </xsl:text>
        </xsl:when>
        <!-- a bad idea for Braille -->
        <xsl:when test="$format-code = 'none'">
            <xsl:text/>
        </xsl:when>
    </xsl:choose>
</xsl:template>


<!-- ####################### -->
<!-- Tabular (table content) -->
<!-- ####################### -->

<!-- Simple tables can be realized nicely in braille by a human transcriber. -->
<!-- We are not even sure how to identify a table as being "simple enough."  -->
<!--                                                                         -->
<!-- So we implement "Wide Tables: Linear Table Format" [BANA, 2016, 11.17], -->
<!-- which is never wrong, and is more or less sympatico with our markup.    -->
<!--                                                                         -->
<!-- TODO: Suppose a transcriber *does* replace one of our tables with       -->
<!-- something better?  We could perhaps capture the BRF version in a new    -->
<!-- "braille" element that lived in source and which was used               -->
<!-- preferentially once discovered.                                         -->

<xsl:template match="tabular">
    <xsl:variable name="n-column-headings" select="count(row[(@header = 'yes') or (@header = 'vertical')])"/>
    <xsl:variable name="b-column-headings" select="$n-column-headings > 0"/>
    <xsl:variable name="b-row-headings" select="@row-headers = 'yes'"/>
    <block breakable="no">
        <!-- Transcriber note, if necessary to explain headings -->
        <xsl:if test="$b-column-headings or $b-row-headings">
            <xsl:apply-templates select="." mode="transcriber-note">
                <xsl:with-param name="message">
                    <xsl:if test="$b-column-headings">
                        <xsl:text>The first </xsl:text>
                        <xsl:value-of select="$n-column-headings"/>
                        <xsl:text> rows are columm headings, described next.</xsl:text>
                    </xsl:if>
                    <!-- separate two sentences, if we have both -->
                    <xsl:if test="$b-column-headings and $b-row-headings">
                        <xsl:text> </xsl:text>
                    </xsl:if>
                    <xsl:if test="$b-row-headings">
                        <xsl:text>The first column of this table contains headings for the rows.</xsl:text>
                    </xsl:if>
                </xsl:with-param>
            </xsl:apply-templates>
            <!-- [BANA, 2016] 11.17.1e "Leave a blank line after the note." -->
            <segment lines-after="1"/>
        </xsl:if>
        <!-- enforce header row(s) first -->
        <!-- BANA says put column headings inside the transcriber note, -->
        <!-- but switch to 1-3 margins.  We ignore this and write the   -->
        <!-- column headings out just tlike all the other rows.  One    -->
        <!-- concession: a blank line separator.                        -->
        <xsl:apply-templates select="row[(@header = 'yes') or (@header = 'vertical')]"/>
        <xsl:if test="$b-column-headings">
            <segment lines-after="1"/>
        </xsl:if>
        <!-- now the "regular" lines, possibly with row-headings -->
        <xsl:apply-templates select="row[not((@header = 'yes') or (@header = 'vertical'))]"/>
    </block>
</xsl:template>

<!-- [BANA, 2016] 11.17.1f Each row has 1-3 margins                     -->
<!-- [BANA, 2016] 11.17.1g "Do not divide a row between braille pages." -->
<xsl:template match="tabular/row">
    <segment breakable="no" indentation="0" runover="2">
        <xsl:choose>
            <xsl:when test="(@header = 'yes') or (@header = 'vertical')">
                <xsl:apply-templates select="cell[1]" mode="describe-column-headings"/>
            </xsl:when>
            <xsl:otherwise>
                <xsl:apply-templates select="cell"/>
            </xsl:otherwise>
        </xsl:choose>
    </segment>
</xsl:template>

<!-- "Regular" cells in non-header rows (more typical) -->
<xsl:template match="tabular/row/cell">
    <xsl:apply-templates/>
    <xsl:choose>
        <!-- First cell, trailed by a colon -->
        <xsl:when test="not(preceding-sibling::cell)">
            <xsl:text>: </xsl:text>
        </xsl:when>
        <!-- Last cell, trailed by nothing -->
        <xsl:when test="not(following-sibling::cell)"/>
        <!-- Interior cells, trailed by semi-colons -->
        <xsl:otherwise>
            <xsl:text>; </xsl:text>
        </xsl:otherwise>
    </xsl:choose>
    <xsl:if test="@colspan">
        <xsl:call-template name="duplicate-string">
             <xsl:with-param name="count" select="@colspan - 1"/>
             <xsl:with-param name="text" select="';'"/>
         </xsl:call-template>
     </xsl:if>
</xsl:template>

<xsl:template match="tabular/row/cell" mode="describe-column-headings">
    <xsl:param name="prior-column-number" select="0"/>

    <!-- Analyze  @colspan  implications.  Note this is correct for -->
    <!-- no attribute at all and a (silly) attribute value of 1.    -->
    <xsl:variable name="first-column" select="$prior-column-number + 1"/>
    <xsl:variable name="n-columns">
        <xsl:choose>
            <xsl:when test="@colspan">
                <xsl:value-of select="@colspan"/>
            </xsl:when>
            <xsl:otherwise>
                <xsl:text>1</xsl:text>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:variable>
    <xsl:variable name="last-column" select="$prior-column-number + $n-columns"/>
    <xsl:variable name="b-multicolumns" select="$last-column > $first-column"/>

    <xsl:text>Column</xsl:text>
    <xsl:if test="$b-multicolumns">
        <xsl:text>s</xsl:text>
    </xsl:if>
    <xsl:text> </xsl:text>
    <xsl:value-of select="$first-column"/>
    <xsl:if test="$b-multicolumns">
        <xsl:text> - </xsl:text>
        <xsl:value-of select="$last-column"/>
    </xsl:if>
    <xsl:text> </xsl:text>
    <xsl:apply-templates/>
    <xsl:choose>
        <!-- First cell, trailed by a colon -->
        <xsl:when test="not(preceding-sibling::cell)">
            <xsl:text>: </xsl:text>
        </xsl:when>
        <!-- Last cell, trailed by nothing -->
        <xsl:when test="not(following-sibling::cell)"/>
        <!-- Interior cells, trailed by semi-colons -->
        <xsl:otherwise>
            <xsl:text>; </xsl:text>
        </xsl:otherwise>
    </xsl:choose>
    <!-- recurse if there is more to do -->
    <xsl:if test="following-sibling::cell">
        <xsl:apply-templates select="following-sibling::cell" mode="describe-column-headings">
            <xsl:with-param name="prior-column-number" select="$last-column"/>
        </xsl:apply-templates>
    </xsl:if>
</xsl:template>

<!-- A "p" normally becomes a "segment".  But an entire row of a "tabular" -->
<!-- is a segment and we can't nest them.  So we just dribble out the      -->
<!-- entire "p" without any indentation or anything, so it becomes one     -->
<!-- very long cell in the braille.  Worse, two "p" in a cell will just    -->
<!-- get concatenated and the distinction between the two will be lost.    -->
<xsl:template match="cell/p">
    <xsl:apply-templates select="node()"/>
    <!-- At least provide a space between consecutive "p" -->
    <xsl:if test="following-sibling::p">
        <xsl:text>&#xa;</xsl:text>
    </xsl:if>
</xsl:template>


<!-- ########## -->
<!-- References -->
<!-- ########## -->

<!-- Bibliography [BANA-2016, 22.2.1]                           -->
<!-- Bibliographic items in a "references" division have a      -->
<!-- bracketed number leading each new entry, then two spaces   -->
<!-- of indentation for the remainder .                         -->
<!-- An annotation ("note") produces a block, so it cannot live -->
<!-- inside the entry's segment; it follows as a sibling.       -->
<!-- TODO: format annotations per BANA 22.3, rather than        -->
<!-- reusing the boxed rendering of a REMARK-LIKE "note".       -->
<xsl:template match="biblio[@type='raw']">
    <runin indentation="0" separator="&#x20;">
        <xsl:text>[</xsl:text>
        <xsl:apply-templates select="." mode="serial-number"/>
        <xsl:text>]</xsl:text>
    </runin>
    <segment indentation="0" runover="2">
        <xsl:apply-templates select="node()[not(self::note)]"/>
    </segment>
    <xsl:apply-templates select="note"/>
</xsl:template>

<!-- Structured bibliographic entries ("bibtex" type, or untyped   -->
<!-- fallback) render their fields in document order, with the     -->
<!-- same [BANA-2016, 22.2.1] margins as the raw flavor above, and -->
<!-- the same treatment of an annotation: a "note" produces a      -->
<!-- block, so it follows the entry as a sibling.                  -->
<xsl:template match="biblio[not(@type = 'raw')]">
    <runin indentation="0" separator="&#x20;">
        <xsl:text>[</xsl:text>
        <xsl:apply-templates select="." mode="serial-number"/>
        <xsl:text>]</xsl:text>
    </runin>
    <segment indentation="0" runover="2">
        <xsl:apply-templates select="*[not(self::note)]"/>
    </segment>
    <xsl:apply-templates select="note"/>
</xsl:template>

<!-- Override usual killing of title, but perhaps a generic -->
<!-- template (without punctuation!) would be saner?        -->
<xsl:template match="biblio/title">
    <italic>
        <xsl:apply-templates/>
    </italic>
</xsl:template>

<xsl:template match="volume">
    <bold>
        <xsl:apply-templates/>
    </bold>
</xsl:template>

<!-- Generators -->

<xsl:template match="pretext">
    <xsl:text>PreTeXt</xsl:text>
</xsl:template>

<xsl:template match="tex">
    <xsl:text>TeX</xsl:text>
</xsl:template>

<xsl:template match="latex">
    <xsl:text>LaTeX</xsl:text>
</xsl:template>

<!-- static, all "webwork" as problems are gone -->
<xsl:template match="webwork">
    <xsl:text>WeBWorK</xsl:text>
</xsl:template>

<xsl:template match="ie">
    <xsl:text>i.e.</xsl:text>
</xsl:template>

<xsl:template match="etc">
    <xsl:text>etc.</xsl:text>
</xsl:template>


<!-- Empty Elements, Characters -->

<!-- Generally Unicode values get translated into UEB equivalents  -->
<!-- by liblouis.  This is based on a reading of                   -->
<!--                                                               -->
<!--     /usr/share/liblouis/tables/en-ueb-chardefs.uti            -->
<!--                                                               -->
<!-- which is incorporated via the English-UEB Grade 1 and Grade 2 -->
<!-- tables.  As of 2023-05-12.  We document the Unicode character -->
<!-- and the cells described in the liblouis table.                -->
<!--                                                               -->
<!-- N.B. there is no attempt here to provide localizations, such  -->
<!-- as quotation mark styles, since we are limited ourselves to   -->
<!-- English language documents by larger decisions elsewhere.     -->

<!-- Each character reads the Unicode column of the representation -->
<!-- table in  pretext-common.xsl.  A "braille" column entry       -->
<!-- substitutes where liblouis lacks the true code point; the      -->
<!-- entry "none" marks a character outside this repertoire,        -->
<!-- which warns, keeping the gap visible.                          -->
<!--                                                                -->
<!-- Cells described in the liblouis table, for each Unicode        -->
<!-- character rendered here:                                       -->
<!--                                                                -->
<!--   nbsp (U+00A0): passed through in-kind; used in the           -->
<!--     manufacture of a cross-reference, we will want to strip    -->
<!--     just before it ends up in BRF                              -->
<!--   ndash (U+2013): 6-36                                         -->
<!--   mdash (U+2014): 6-36                                         -->
<!--   thin-space (U+2009): 0, a braille space                     -->
<!--   copyright (U+00A9): 45-14                                    -->
<!--   registered (U+00AE): 45-1235                                 -->
<!--   trademark (U+2122): 45-2345                                  -->
<!--   degree (U+00B0): 45-245                                      -->
<!--   prime (U+2032): 2356                                         -->
<!--   dblprime (U+2033): 2356-2356                                 -->
<!--   langle (U+3008): 4-126                                       -->
<!--   rangle (U+3009): 4-345                                       -->
<!--   ellipsis (U+2026): 256-256-256; [BANA-2016] Appendix G,      -->
<!--     UEB is three periods/256                                   -->
<!--   midpoint (U+00B7): 4-16                                      -->
<!--   swungdash: faked with TILDE (U+007E)                         -->
<!--   pilcrow (U+00B6): 45-1234                                    -->
<!--   section-mark (U+00A7): 45-234                                -->
<!--   minus (U+2212): 5-36                                         -->
<!--   times (U+00D7): 5-236                                        -->
<!--   solidus: faked with SOLIDUS (U+002F)                         -->
<!--   obelus (U+00F7): 5-34                                        -->
<!--   plusminus (U+00B1): 456-235                                  -->
<xsl:template match="char" mode="character">
    <xsl:choose>
        <xsl:when test="@braille = 'none'">
            <xsl:call-template name="warn-unimplemented-character">
                <xsl:with-param name="char-name" select="@name"/>
            </xsl:call-template>
        </xsl:when>
        <xsl:when test="@braille">
            <xsl:value-of select="@braille"/>
        </xsl:when>
        <xsl:otherwise>
            <xsl:value-of select="@unicode"/>
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>

<!-- the CJK angle brackets: the liblouis table defines cells -->
<!-- (above) only for these, not for the mathematical pair    -->
<!-- carried by the representation table                      -->
<xsl:template match="char[@name = 'langle']" mode="character">
    <xsl:text>&#x3008;</xsl:text>
</xsl:template>
<xsl:template match="char[@name = 'rangle']" mode="character">
    <xsl:text>&#x3009;</xsl:text>
</xsl:template>

<!-- Unicode Character 'LEFT SINGLE QUOTATION MARK' (U+2018) -->
<!-- Liblouis: 6-236                                         -->
<xsl:template match="*" mode="lsq-character">
    <xsl:text>&#x2018;</xsl:text>
</xsl:template>

<!-- Unicode Character 'RIGHT SINGLE QUOTATION MARK' (U+2019) -->
<!-- Liblouis: 6-356                                          -->
<xsl:template match="*" mode="rsq-character">
    <xsl:text>&#x2019;</xsl:text>
</xsl:template>

<!-- Unicode Character 'LEFT DOUBLE QUOTATION MARK' (U+201C) -->
<!-- Liblouis: 236                                           -->
<xsl:template match="*" mode="lq-character">
    <xsl:text>&#x201C;</xsl:text>
</xsl:template>

<!-- Unicode Character 'RIGHT DOUBLE QUOTATION MARK' (U+201D) -->
<!-- Liblouis: 356                                            -->
<xsl:template match="*" mode="rq-character">
    <xsl:text>&#x201D;</xsl:text>
</xsl:template>


<!-- Icons -->
<!-- Just the four arrows, unsure about the rest -->
<!-- Arrows are in liblouis table                -->

<xsl:template match="icon">
    <xsl:choose>
        <xsl:when test="@name = 'arrow-left'">
            <xsl:text>&#x2190;</xsl:text>
        </xsl:when>
        <xsl:when test="@name ='arrow-up'">
            <xsl:text>&#x2191;</xsl:text>
        </xsl:when>
        <xsl:when test="@name = 'arrow-right'">
            <xsl:text>&#x2192;</xsl:text>
        </xsl:when>
        <xsl:when test="@name ='arrow-down'">
            <xsl:text>&#x2193;</xsl:text>
        </xsl:when>
        <xsl:otherwise>
            <xsl:message>PTX:WARNING: &quot;icon&quot; with @name attribute value "<xsl:value-of select="@name"/>" does not have an implementation for braille.</xsl:message>
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>


<!-- ############ -->
<!-- Font Changes -->
<!-- ############ -->

<!-- Certain PreTeXt groupings in running text naturally yield just  -->
<!-- a font change.  Braille and liblouis have facilities for italic -->
<!-- and bold.  This is "internal" markup that eventually gets       -->
<!-- interpreted by  lxml  in Python.                                -->

<!-- Italics -->
<xsl:template match="em|foreign|articletitle|pubtitle">
    <!-- Python will assume "italic" as element name -->
    <italic>
        <xsl:apply-templates select="node()"/>
    </italic>
</xsl:template>

<!-- Bold -->
<xsl:template match="term|alert">
    <!-- Python will assume "bold" as element name -->
    <bold>
        <xsl:apply-templates select="node()"/>
    </bold>
</xsl:template>

<!-- Biological Names -->
<xsl:template match="taxon">
    <!-- In italic font -->
    <italic>
        <xsl:choose>
            <!-- both substructures -->
            <xsl:when test="genus and species">
                <xsl:apply-templates select="genus"/>
                <xsl:text> </xsl:text>
                <xsl:apply-templates select="species"/>
            </xsl:when>
            <!-- just one -->
            <xsl:when test="genus">
                <xsl:apply-templates select="genus"/>
            </xsl:when>
            <!-- just the other one -->
            <xsl:when test="species">
                <xsl:apply-templates select="species"/>
            </xsl:when>
            <!-- not structured, use content -->
            <xsl:otherwise>
                <xsl:apply-templates/>
            </xsl:otherwise>
        </xsl:choose>
    </italic>
</xsl:template>

<!-- Code -->
<!-- Accomplished in UEB Grade 2, but with transcriber emphasis scheme 1 -->
<!-- from liblouis (where is this defined?).  See liblouis table         -->
<!-- "en-ueb-g1.ctb" for exact definition of emphasis code "trans1".     -->
<!--                                                                     -->
<!--     emphletter trans1 4-3456-23                                     -->
<!--     begemphword trans1 4-3456-2                                     -->
<!--     endemphword trans1 4-3456-3                                     -->
<!--     lenemphphrase trans1 3                                          -->
<!--     begemphphrase trans1 4-3456-2356                                -->
<!--     endemphphrase trans1 after 4-3456-3                             -->
<xsl:template name="code-wrapper">
    <xsl:param name="content"/>

    <code>
        <xsl:value-of select="$content"/>
    </code>
</xsl:template>

<!-- Pass-through/Dropped -->
<xsl:template match="abbr|acro|init">
    <xsl:apply-templates select="node()"/>
</xsl:template>

<!-- "idx" must be dealt with from source otherwise during    -->
<!-- index construction, but when encountered in a paragraph  -->
<!-- or a block they should just be killed.  Should never     -->
<!-- reach an interior "h".  Entirely similar for "notation"  -->
<!-- and an interior "usage", and "description".              -->

<xsl:template match="idx|notation"/>

<!-- Documenting PreText itself -->

<xsl:template match="tag">
    <xsl:text>&lt;</xsl:text>
    <xsl:value-of select="."/>
    <xsl:text>&gt;</xsl:text>
</xsl:template>

<xsl:template match="tage">
    <xsl:text>&lt;</xsl:text>
    <xsl:value-of select="."/>
    <xsl:text>/&gt;</xsl:text>
</xsl:template>

<xsl:template match="attr">
    <xsl:text>@</xsl:text>
    <xsl:value-of select="."/>
</xsl:template>

<!-- #### -->
<!-- Math -->
<!-- #### -->

<xsl:template match="m[not(contains(math-nemeth, '&#xa;'))]">
    <!-- Unicode braille cells from Speech Rule Engine (SRE)   -->
    <!-- Not expecting any markup, so "value-of" is everything -->
    <!-- Possibly converted to BRF ASCII symbols ("early")     -->
    <xsl:variable name="raw-braille">
        <xsl:call-template name="brf-symbols-filter">
            <xsl:with-param name="text" select="math-nemeth"/>
        </xsl:call-template>
    </xsl:variable>
    <!-- We investigate actual source for very simple math   -->
    <!-- such as one-letter variable names as Latin letters  -->
    <!-- or positive integers, so we process the orginal     -->
    <!-- content outside of a MathJax/SRE translation (which -->
    <!-- could have "xref", etc)                             -->
    <xsl:variable name="content">
        <xsl:value-of select="math-original/node()"/>
    </xsl:variable>
    <xsl:variable name="original-content" select="normalize-space($content)"/>
    <!-- Note: this mark is *always* removed from the trailing text node,    -->
    <!-- so we need to *always* restore it.  In other wordds, we usually     -->
    <!-- put it into an attribute to get picked up by  lxml  in the Python.  -->
    <!-- But if we short-circuit that process here by turning integers into  -->
    <!-- digits or making single-letter variables unadorned, then we need to -->
    <!-- restore the mark in this template.                                  -->
    <xsl:variable name="clause-ending-mark">
        <xsl:apply-templates select="." mode="get-clause-punctuation-mark"/>
    </xsl:variable>
    <!-- Various cases, more specific first -->
    <xsl:choose>
        <!-- Inline math with just one Latin letter. No formatting,  -->
        <!-- no italics, according to BANA rules via Michael Cantino -->
        <!-- (2023-01-26) so drop-in $original.  C'est la vie.       -->
        <xsl:when test="(string-length($original-content) = 1) and contains(&ALPHABET;, $original-content)">
            <xsl:value-of select="$original-content"/>
            <!-- restore clause-ending punctuation -->
            <xsl:value-of select="$clause-ending-mark"/>
        </xsl:when>
        <!-- Test is true for non-negative integers, which we drop into -->
        <!-- the stream as if they were never authored as math anyway   -->
        <xsl:when test="translate($original-content, &DIGIT; ,'') = ''">
            <xsl:value-of select="$original-content"/>
            <!-- restore clause-ending punctuation -->
            <xsl:value-of select="$clause-ending-mark"/>
        </xsl:when>
        <!-- We construct a fragment for the Python formatter.   -->
        <!-- SRE may convert inline "m" into a spatial layout,   -->
        <!-- such as a fraction or column vector authored inline -->
        <!-- We treat this elsewhere, more like "md" elements    -->
        <xsl:otherwise>
            <math>
                <!-- Add punctuation as an attribute conditionally. -->
                <!-- We could probably just add an empty string     -->
                <!-- routinely and push that through to the closing -->
                <!-- Nemeth indicator, but we take a bit more care. -->
                <xsl:if test="not($clause-ending-mark = '')">
                    <xsl:attribute name="punctuation">
                        <xsl:value-of select="$clause-ending-mark"/>
                    </xsl:attribute>
                </xsl:if>
                <xsl:value-of select="$raw-braille"/>
            </math>
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>

<xsl:template match="m[contains(math-nemeth, '&#xa;')]|md">
    <!-- Lines are trimmed, and possibly converted to BRF ASCII -->
    <!-- symbols ("early"), one at a time, below                -->
    <xsl:variable name="nemeth">
        <xsl:value-of select="math-nemeth"/>
        <xsl:text>&#xa;</xsl:text>
    </xsl:variable>
    <block breakable="no" box="nemeth">
        <xsl:attribute name="punctuation">
            <xsl:apply-templates select="." mode="get-clause-punctuation-mark"/>
        </xsl:attribute>
        <xsl:call-template name="segmentize-display-math">
            <xsl:with-param name="display-math" select="$nemeth"/>
        </xsl:call-template>
    </block>
</xsl:template>

<xsl:template name="segmentize-display-math">
    <xsl:param name="display-math"/>

    <xsl:choose>
        <!-- done, nothing left to work on -->
        <xsl:when test="$display-math = ''"/>
        <xsl:otherwise>
            <!-- first line into a segment: trailing blank cells -->
            <!-- trimmed first, and then a possible conversion to -->
            <!-- BRF ASCII symbols ("early"), line by line, so a  -->
            <!-- line of print residue rides along as Unicode     -->
            <!-- without disqualifying its neighbors              -->
            <segment>
                <xsl:variable name="trimmed">
                    <xsl:call-template name="trim-nemeth-trailing-whitespace">
                        <xsl:with-param name="text" select="substring-before($display-math, '&#xa;')"/>
                    </xsl:call-template>
                </xsl:variable>
                <xsl:call-template name="brf-symbols-filter">
                    <xsl:with-param name="text" select="$trimmed"/>
                </xsl:call-template>
            </segment>
            <!-- recurse on remainder -->
            <xsl:call-template name="segmentize-display-math">
                <xsl:with-param name="display-math" select="substring-after($display-math, '&#xa;')"/>
            </xsl:call-template>
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>


<!-- ################ -->
<!-- Cross-References -->
<!-- ################ -->

<!-- Simple implementations of the basic -->
<!-- components of a cross-reference     -->

<!-- This device is just for the LaTeX conversion -->
<xsl:template match="*" mode="xref-number">
    <xsl:apply-templates select="." mode="number"/>
</xsl:template>

<!-- Nothing much to be done, we just -->
<!-- xerox the text representation    -->
<xsl:template match="*" mode="xref-link">
    <xsl:param name="target" />
    <xsl:param name="content" />

    <xsl:copy-of select="$content"/>
</xsl:template>

<!-- #### -->
<!-- URLs -->
<!-- #### -->

<!-- Some technical debt: these to variables (or at least one) should -->
<!-- perhaps be placed in -common rather than duplicating them.       -->

<!-- 2023-03-06: these two vraiables have been copied verbatim from the HTML conversion -->

<xsl:template match="url|dataurl">
    <!-- link/reference/location may be external -->
    <!-- (@href) or internal (dataurl[@source])  -->
    <xsl:variable name="uri">
        <xsl:choose>
            <!-- "url" and "dataurl" both support external @href -->
            <xsl:when test="@href">
                <xsl:value-of select="@href"/>
            </xsl:when>
            <!-- a "dataurl" might be local, @source is      -->
            <!-- indication, so prefix with a local path/URI -->
            <xsl:when test="self::dataurl and @source">
                <!-- empty when not using managed directories -->
                <xsl:value-of select="$external-directory"/>
                <xsl:value-of select="@source"/>
            </xsl:when>
            <!-- empty will be non-functional -->
            <xsl:otherwise/>
        </xsl:choose>
    </xsl:variable>
    <!-- visible portion of HTML is the URL itself,   -->
    <!-- formatted as code, or content of PTX element -->
    <xsl:variable name="visible-text">
        <xsl:choose>
            <xsl:when test="node()">
                <xsl:apply-templates/>
            </xsl:when>
            <xsl:otherwise>
                <code class="code-inline tex2jax_ignore">
                    <xsl:choose>
                        <xsl:when test="@visual">
                            <xsl:value-of select="@visual"/>
                        </xsl:when>
                        <xsl:otherwise>
                            <xsl:value-of select="$uri"/>
                        </xsl:otherwise>
                    </xsl:choose>
                </code>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:variable>

    <xsl:value-of select="$visible-text"/>
</xsl:template>


<!-- ######### -->
<!-- Footnotes -->
<!-- ######### -->

<!-- Drop a mark at sight, Need to devise an        -->
<!-- add-on to division-processing to make endnotes -->
<!-- [BANA-2016] 16.1.4(g): (print observations)  -->
<!-- In a note section, either at the end of each -->
<!-- chapter or at the back of the book.          -->
<!-- [BANA-2016] 16.1.5(c): (braille placement)   -->
<!-- At the end of the chapter or volume.         -->

<!-- BANA 16.2.2: superscripted number          -->
<!-- (two-cell indicator, number sign, number). -->
<!-- TODO: collect footnote *content* at division ends -->
<xsl:template match="fn">
    <!--  5-6  3-5  -->
    <xsl:text>&#x2830;&#x2814;</xsl:text>
    <!-- A number sign is supplied by liblouis translation -->
    <!-- 2-4-5-6  U+283C                                   -->
    <xsl:apply-templates select="." mode="number"/>
    <!-- trailing space necessary to end superscript?  -->
    <!-- will get merged with any that already exists? -->
    <xsl:text> </xsl:text>
</xsl:template>


<!-- ################# -->
<!-- Verbatim, Program -->
<!-- ################# -->

<!-- Various templates elsewhere manipulate large chunks of verbatim text, -->
<!-- such as for a "program".  We leverage those as much as possible.      -->
<!-- Ideally we easily get a chunk of text, given as a sequence of lines   -->
<!-- defined by newline characters.   The recursive "braille-source-code"  -->
<!-- template makes a "segment" for each line, this will allow for runover -->
<!-- and *code* indentation without any ambiguity.  So most of the braille -->
<!-- formatting happens in this template.                                  -->
<!--                                                                       -->
<!-- IMPORTANT: ensure that $text has a final newline character.           -->

<xsl:template name="braille-source-code">
    <xsl:param name="text"/>

    <xsl:choose>
        <!-- $text always ends in a newline, so final recursive call will    -->
        <!-- have an empty string.  This is the indication that we are done. -->
        <xsl:when test="$text = ''"/>
        <!-- Nonempty $text, so split it, and recurse -->
        <xsl:otherwise>
            <segment indentation="0" runover="0">
                <code>
                    <xsl:value-of select="substring-before($text, '&#xa;')"/>
                </code>
            </segment>
            <xsl:call-template name="braille-source-code">
                <xsl:with-param name="text" select="substring-after($text, '&#xa;')"/>
            </xsl:call-template>
        </xsl:otherwise>
    </xsl:choose>
</xsl:template>

<!-- A "cd" is structured with "cline" or not.  We do not sanitize, that   -->
<!-- tis what the "cline"element is for - control over leading whitespace. -->
<!-- We provide a final newline here for a bare "cd", otherwise the        -->
<!-- "cline" template provides it.                                         -->
<xsl:template match="cd">
    <block breakable="no">
        <xsl:call-template name="braille-source-code">
            <xsl:with-param name="text">
                <xsl:choose>
                    <xsl:when test="cline">
                        <xsl:apply-templates select="cline"/>
                    </xsl:when>
                    <xsl:otherwise>
                        <xsl:value-of select="."/>
                        <xsl:text>&#xa;</xsl:text>
                    </xsl:otherwise>
                </xsl:choose>
            </xsl:with-param>
        </xsl:call-template>
    </block>
</xsl:template>

<!-- "pre" and "pre[cline]" are handled by the "interior" -->
<!-- modal template in -common.                           -->
<!-- "pre" uses "sanitize-text", which provides a final   -->
<!-- newline, while "pre[cline]" uses the base "cline"    -->
<!-- template, which also provides a final newline.       -->
<xsl:template match="pre">
    <block breakable="no">
        <xsl:call-template name="braille-source-code">
            <xsl:with-param name="text">
                <xsl:apply-templates select="." mode="interior"/>
            </xsl:with-param>
        </xsl:call-template>
    </block>
</xsl:template>

<!-- A "program" gets a lot of treatment in other formats to recognize   -->
<!-- the language an author specifies and then do some sort of syntax    -->
<!-- highlighting with fonts and colors.  That would be hard in braille, -->
<!-- and we don't know of a good tool anyway.  So we just echo the       -->
<!-- "input" portion.                                                    -->
<!-- "sanitize-text" provides a final newline, always                    -->
<xsl:template match="program">
    <!-- build up full program text so we can apply sanitize-text to entire blob -->
    <!-- and thus allow relative indentation for preamble/code/postamble         -->
    <xsl:variable name="program-text">
        <xsl:variable name="program-text">
            <xsl:if test="preamble[not(@visible = 'no')]">
                <xsl:call-template name="substring-before-last">
                    <xsl:with-param name="input" select="preamble" />
                    <xsl:with-param name="substr" select="'&#xA;'" />
                </xsl:call-template>
            </xsl:if>
            <xsl:call-template name="substring-before-last">
                <xsl:with-param name="input" select="code" />
                <xsl:with-param name="substr" select="'&#xA;'" />
            </xsl:call-template>
            <xsl:text>&#xA;</xsl:text>
            <xsl:if test="postamble[not(@visible = 'no')]">
                <xsl:value-of select="substring-after(postamble,'&#xA;')" />
            </xsl:if>
        </xsl:variable>
    </xsl:variable>
    <block breakable="no">
        <xsl:call-template name="braille-source-code">
            <xsl:with-param name="text">
                <xsl:call-template name="sanitize-text">
                    <xsl:with-param name="text" select="$program-text" />
                </xsl:call-template>
            </xsl:with-param>
        </xsl:call-template>
    </block>
</xsl:template>

<!-- For a "console" session, we work hardest on the "input", pulling in -->
<!-- a preceding prompt, and considering the possibility of no "output". -->
<!-- For "output", if extant, we provide necessary separators.           -->

<xsl:template match="console">
    <!-- entire session as a block -->
    <block breakable="no" lines-before="1" lines-after="1">
        <!-- respect authored order, so don't split these -->
        <xsl:apply-templates select="input|output"/>
    </block>
</xsl:template>

<xsl:template match="console/input">
    <xsl:variable name="console-input">
        <!-- prompt first, if provided; author provides -->
        <!-- any space that prompt would create         -->
        <xsl:value-of select="preceding-sibling::*[1][self::prompt]"/>
        <!-- remainder of the input -->
        <xsl:call-template name="sanitize-text">
            <xsl:with-param name="text" select="."/>
        </xsl:call-template>
    </xsl:variable>
    <!-- now feed to braille-ification -->
    <xsl:call-template name="braille-source-code">
        <xsl:with-param name="text" select="$console-input"/>
    </xsl:call-template>
    <!-- add a blank line, only when not provided by the output -->
    <xsl:if test="not(following-sibling::*[1][self::output])">
        <segment lines-before="1"/>
    </xsl:if>
</xsl:template>

<xsl:template match="console/output">
    <xsl:variable name="console-output">
        <!-- separate from the input -->
        <!-- NB: newline here necessary for textual version -->
        <xsl:text>---------------&#xa;</xsl:text>
        <!-- remainder of the input -->
        <xsl:call-template name="sanitize-text">
            <xsl:with-param name="text" select="."/>
        </xsl:call-template>
    </xsl:variable>
    <!-- now feed to braille-ification -->
    <xsl:call-template name="braille-source-code">
        <xsl:with-param name="text" select="$console-output"/>
    </xsl:call-template>
    <!-- and a blank line to help with session -->
    <segment lines-before="1"/>
</xsl:template>

<!-- Sage cells rely on per-conversion overrides of presumed   -->
<!-- abstract templates, to handle the numerous possibilities. -->
<!-- Using a long line to simulate input/output split          -->

<xsl:template match="sage" mode="sage-active-markup">
    <xsl:param name="in" />
    <xsl:param name="out" />

    <block breakable="no" lines-before="1" lines-after="1">
        <xsl:call-template name="braille-source-code">
            <xsl:with-param name="text" select="$in"/>
        </xsl:call-template>

        <xsl:if test="not($out = '')">
            <segment>
                <xsl:text>-----------------</xsl:text>
            </segment>
            <xsl:call-template name="braille-source-code">
                <xsl:with-param name="text" select="$out"/>
            </xsl:call-template>
        </xsl:if>
    </block>
</xsl:template>

<!-- Display only, just input -->
<xsl:template name="sage-display-markup">
    <xsl:param name="in" />

    <block breakable="no" lines-before="1" lines-after="1">
        <xsl:call-template name="braille-source-code">
            <xsl:with-param name="text" select="$in"/>
        </xsl:call-template>
    </block>
</xsl:template>


<!-- ############# -->
<!-- Miscellaneous -->
<!-- ############# -->

<!-- Containers that have zero metadata (no title, etc.) -->
<xsl:template match="statement|introduction|conclusion">
    <xsl:apply-templates select="*"/>
</xsl:template>

<!-- Just text nodes, but might have a WeBWorK -->
<!-- "var", so process all children            -->
<xsl:template match="shortdescription">
    <xsl:apply-templates/>
</xsl:template>

<!-- fillin blanks, outside math -->
<!-- A fillin inside math will have disappeared on us by now, -->
<!-- it was mixed into some LaTeX syntax and has been gobbled -->
<!-- up by MathJax by now.  So the conditional here is really -->
<!-- moot and not necessary.                                  -->
<!-- [BANA, 2016] 10.6.2 and Michael Cantino: an underscore   -->
<!-- Seems to translate as a "sign": 46-36 in liblouis table  -->
<xsl:template match="fillin[not(parent::m or parent::mrow)]">
    <xsl:text>_</xsl:text>
</xsl:template>

<!-- Fillin blanks, inside math -->
<!-- For math see https://nemeth.aphtech.org/lesson3.5 4x U+2824 -->

<!-- ############ -->
<!-- EXPERIMENTAL -->
<!-- ############ -->

<!-- A paragraph without "displays" is straightforward and -->
<!-- we can bypass the more complicated procedure next.    -->
<xsl:template match="p">
    <!-- Inside a list item ($list-runover is a number, not empty)  -->
    <!-- every line of the paragraph belongs at the list's runover  -->
    <!-- margin [BANA-2016, 8.5.1(b)]; the melded run-in marker     -->
    <!-- supplies the first paragraph's first-line position.        -->
    <xsl:param name="list-runover" select="''"/>
    <segment>
        <xsl:attribute name="indentation">
            <xsl:choose>
                <xsl:when test="not($list-runover = '')">
                    <xsl:value-of select="$list-runover"/>
                </xsl:when>
                <xsl:when test="@pi:indent = 'no'">
                    <xsl:text>0</xsl:text>
                </xsl:when>
                <xsl:otherwise>
                    <xsl:text>2</xsl:text>
                </xsl:otherwise>
            </xsl:choose>
        </xsl:attribute>
        <xsl:if test="not($list-runover = '')">
            <xsl:attribute name="runover">
                <xsl:value-of select="$list-runover"/>
            </xsl:attribute>
        </xsl:if>
        <xsl:apply-templates select="node()"/>
    </segment>
</xsl:template>

<!-- Two-dimensional displayed itmes will get their own segment and   -->
<!-- we will explode the rest of a "p" into pieces that are segments. -->
<!-- But with indentation only on the first piece.                    -->
<!-- Note: leading with a display in a "p" means no indentation.      -->
<!-- Note: this is derived from a similar template in the HTML        -->
<!-- conversion.                                                      -->
<xsl:template match="p[ol|ul|dl|m[contains(math-nemeth, '&#xa;')]|md|cd]">
    <!-- Inside a list item ($list-runover is a number, not empty)  -->
    <!-- every piece of the paragraph belongs at the list's runover -->
    <!-- margin [BANA-2016, 8.5.1(b)]; nested lists among the       -->
    <!-- displays compute their own, deeper, margins.               -->
    <xsl:param name="list-runover" select="''"/>
    <!-- will later loop over displays within paragraph      -->
    <!-- match guarantees at least one for $initial variable -->
    <xsl:variable name="displays" select="ul|ol|dl|m[contains(math-nemeth, '&#xa;')]|md|cd" />
    <!-- content prior to first display is exceptional, but if empty,   -->
    <!-- as indicated by $initial, we do not produce an empty paragraph -->
    <!--                                                                -->
    <!-- all interesting nodes of paragraph, before first display       -->
    <xsl:variable name="initial" select="$displays[1]/preceding-sibling::node()"/>
    <xsl:variable name="initial-content">
        <xsl:apply-templates select="$initial"/>
    </xsl:variable>
    <xsl:if test="not(normalize-space($initial-content) = '')">
        <segment>
            <xsl:attribute name="indentation">
                <xsl:choose>
                    <xsl:when test="not($list-runover = '')">
                        <xsl:value-of select="$list-runover"/>
                    </xsl:when>
                    <xsl:otherwise>
                        <xsl:text>2</xsl:text>
                    </xsl:otherwise>
                </xsl:choose>
            </xsl:attribute>
            <xsl:if test="not($list-runover = '')">
                <xsl:attribute name="runover">
                    <xsl:value-of select="$list-runover"/>
                </xsl:attribute>
            </xsl:if>
            <xsl:apply-templates select="$initial"/>
        </segment>
    </xsl:if>
    <!-- for each display, output the display, plus trailing content -->
    <xsl:for-each select="$displays">
        <!-- do the display proper -->
        <xsl:apply-templates select="."/>
        <!-- look through remainder, all element and text nodes, and the next display -->
        <xsl:variable name="rightward" select="following-sibling::node()" />
        <xsl:variable name="next-display" select="following-sibling::*[self::ul or self::ol or self::dl or self::m[contains(math-nemeth, '&#xa;')] or self::md or self::cd][1]" />
        <xsl:choose>
            <xsl:when test="$next-display">
                <xsl:variable name="leftward" select="$next-display/preceding-sibling::node()" />
                <!-- device below forms set intersection -->
                <xsl:variable name="common" select="$rightward[count(. | $leftward) = count($leftward)]" />
                <!-- Careful, punctuation after display math      -->
                <!-- gets absorbed into display and so is a node  -->
                <!-- that produces no content (cannot just count) -->
                <xsl:variable name="common-content">
                    <xsl:apply-templates select="$common"/>
                </xsl:variable>
                <xsl:if test="not(normalize-space($common-content) = '')">
                    <segment>
                        <xsl:if test="not($list-runover = '')">
                            <xsl:attribute name="indentation">
                                <xsl:value-of select="$list-runover"/>
                            </xsl:attribute>
                            <xsl:attribute name="runover">
                                <xsl:value-of select="$list-runover"/>
                            </xsl:attribute>
                        </xsl:if>
                        <xsl:apply-templates select="$common"/>
                    </segment>
                </xsl:if>
            </xsl:when>
            <xsl:otherwise>
                <!-- finish the trailing content, if nonempty -->
                <xsl:variable name="final-content">
                    <xsl:apply-templates select="$rightward"/>
                </xsl:variable>
                <xsl:if test="not(normalize-space($final-content) = '')">
                    <segment>
                        <xsl:if test="not($list-runover = '')">
                            <xsl:attribute name="indentation">
                                <xsl:value-of select="$list-runover"/>
                            </xsl:attribute>
                            <xsl:attribute name="runover">
                                <xsl:value-of select="$list-runover"/>
                            </xsl:attribute>
                        </xsl:if>
                        <xsl:apply-templates select="$rightward"/>
                    </segment>
                </xsl:if>
            </xsl:otherwise>
        </xsl:choose>
    </xsl:for-each>
</xsl:template>

<!-- We support books and articles, though nothing in particular -->
<!-- needs to be done at these root elements.  Yet?              -->
<xsl:template match="book|article">
    <xsl:apply-templates select="*"/>
</xsl:template>

<!-- "docinfo" should *always* be mined directly for pieces that affect output -->
<xsl:template match="docinfo"/>

<!-- Many pieces of the "frontmatter" have templates designed for divisions -->
<xsl:template match="frontmatter">
    <xsl:apply-templates select="*"/>
</xsl:template>

<!-- The "titlepage" and front "colophon" should be mined to form front -->
<!-- matter material in the right places, etc.  We kill them for now so -->
<!-- we don't see their children being overlooked.  "bibinfo" is pure   -->
<!-- metadata (authors, date, edition), mined by a title page when one  -->
<!-- is implemented; unhandled, its text leaks into the output stream   -->
<!-- with no anchor, so it is silenced the same way.                    -->
<xsl:template match="titlepage"/>
<xsl:template match="frontmatter/colophon"/>
<!-- TODO: a braille title page [BANA-2016, 2.3] should mine     -->
<!-- "bibinfo" (title, authors, date, edition) rather than       -->
<!-- leaving it silenced here.                                   -->
<xsl:template match="bibinfo"/>

<!-- Many pieces of the "backmatter" have templates designed for divisions -->
<xsl:template match="backmatter">
    <xsl:apply-templates select="*"/>
</xsl:template>


<!-- ############ -->
<!-- EXPERIMENTAL -->
<!-- ############ -->

<!-- These elements are fully handled by common (or by a braille      -->
<!-- character mode defined above), so the coverage catch-all at      -->
<!-- the end of this section excludes them in its "not(...)"          -->
<!-- list and they fall through, rather than report "Overlooked".     -->
<!-- This replaced a block of one-line "apply-imports" shims.         -->

<!-- nbsp, ndash, mdash: characters defined above -->
<!-- copyright, registered, trademark, degree, prime, dblprime, lsq, rsq, lq, rq, langle, rangle, ellipsis, midpoint, pilcrow, section-mark, minus, times, obelus, plusminus: empty character elements defined above -->
<!-- phonomark, copyleft, servicemark, ldblbracket, rdblbracket, swungdash, permille, solidus: lack liblouis translations, so common's versions emit an accurate unimplemented-character warning (move a character up as it is implemented) -->
<!-- q, sq, dblbrackets, angles: groupings of the characters above -->
<!-- xref: xref-number and xref-link defined above -->
<!-- today, timeofday: pure text in common -->
<!-- ad, am, bc, ca, eg, etal, etc, ie, nb, pm, ps, vs, viz: Latin abbreviations, defined as text in common -->
<!-- title, subtitle, shorttitle, plaintitle, creator: killed in common as metadata -->
<!-- caption: killed in common as metadata -->
<!-- cline: a simple template in common is active -->
<!-- c: a simple template in common is active -->
<!-- sage: handled in common -->
<!-- rename: localizations happen in common -->


<!-- Larger structures, needing implementation, *along with* interior -->
<!-- structures.  We report AND include a textual place holder.       -->

<xsl:template match="notation-list">
    <segment>NOTATIONLIST</segment>
</xsl:template>

<!-- A real braille index awaits future work; until then the     -->
<!-- omission is announced in place, rather than silent.  (The    -->
<!-- prior placeholder was bare text, which the renderer cannot   -->
<!-- anchor, so nothing at all appeared.)                         -->
<xsl:template match="index-list">
    <xsl:apply-templates select="." mode="transcriber-note">
        <xsl:with-param name="message">
            <xsl:text>The index is not reproduced in this braille edition.</xsl:text>
        </xsl:with-param>
    </xsl:apply-templates>
</xsl:template>

<xsl:template match="poem">
    <segment>POEM</segment>
</xsl:template>

<!-- Next two are not structures, so as "text" -->

<xsl:template match="quantity">
    <xsl:text>QUANTITY</xsl:text>
</xsl:template>

<xsl:template match="kbd">
    <xsl:text>KBD</xsl:text>
</xsl:template>

<xsl:template name="missing-warning">
    <xsl:if test="//notation-list">
        <xsl:call-template name="missing-implementation">
            <xsl:with-param name="element" select="'notation-list'"/>
            <xsl:with-param name="ntimes" select="count(//notation-list)"/>
        </xsl:call-template>
    </xsl:if>
    <!--  -->
    <xsl:if test="//poem">
        <xsl:call-template name="missing-implementation">
            <xsl:with-param name="element" select="'poem'"/>
            <xsl:with-param name="ntimes" select="count(//poem)"/>
        </xsl:call-template>
    </xsl:if>
    <!--  -->
    <xsl:if test="//quantity">
        <xsl:call-template name="missing-implementation">
            <xsl:with-param name="element" select="'quantity'"/>
            <xsl:with-param name="ntimes" select="count(//quantity)"/>
        </xsl:call-template>
    </xsl:if>
    <!--  -->
    <xsl:if test="//kbd">
        <xsl:call-template name="missing-implementation">
            <xsl:with-param name="element" select="'kbd'"/>
            <xsl:with-param name="ntimes" select="count(//kbd)"/>
        </xsl:call-template>
    </xsl:if>
    <!--  -->
</xsl:template>

<xsl:template name="missing-implementation">
    <xsl:param name="element"/>
    <xsl:param name="ntimes"/>

    <xsl:message>PTX:INFO: Unimplemented: <xsl:value-of select="$element"/> (<xsl:value-of select="$ntimes"/> times)</xsl:message>
</xsl:template>

<xsl:template match="*" mode="overlooked">
    <xsl:message>PTX:INFO: Overlooked: <xsl:value-of select="local-name()"/></xsl:message>
</xsl:template>

<!-- *Every* element needs an implementation, or it ends up here being -->
<!-- reported as overlooked.  Elements handled by common are named in  -->
<!-- the exclusion list, so they fall through; this is temporary       -->
<!-- during development and, once the list empties, can be removed.    -->
<xsl:template priority="-0.5" match="*[not(
        self::nbsp or self::ndash or self::mdash or
        self::copyright or self::registered or self::trademark or self::degree or self::prime or self::dblprime or self::lsq or self::rsq or self::lq or self::rq or self::langle or self::rangle or self::ellipsis or self::midpoint or self::pilcrow or self::section-mark or self::minus or self::times or self::obelus or self::plusminus or
        self::phonomark or self::copyleft or self::servicemark or self::ldblbracket or self::rdblbracket or self::swungdash or self::permille or self::solidus or
        self::q or self::sq or self::dblbrackets or self::angles or
        self::xref or
        self::today or self::timeofday or
        self::ad or self::am or self::bc or self::ca or self::eg or self::etal or self::etc or self::ie or self::nb or self::pm or self::ps or self::vs or self::viz or
        self::title or self::subtitle or self::shorttitle or self::plaintitle or self::creator or
        self::caption or
        self::cline or
        self::c or
        self::sage or
        self::rename)]">
    <xsl:apply-templates select="." mode="overlooked"/>
    <!-- recurse into child elements to find more "missing" elements -->
    <xsl:apply-templates select="*"/>
</xsl:template>

<!-- ######### -->
<!-- Utilities -->
<!-- ######### -->

<!-- Transcriber Notes -->

<!-- Here code is the transcriber, so we can explain places where we   -->
<!-- have done something different than it might be realized in print. -->
<!--                                                                   -->
<!-- [BANA 2016] 3.2.1                                                 -->
<!-- Two three-cell sequences indicate the begin and end of a          -->
<!-- transcriber note.  Additionally, the indentation is 7-5 margins.  -->
<!--                                                                   -->
<!-- The content provided in the "message" parameter by a calling      -->
<!-- instance will be placed into a segment, so this is not an         -->
<!-- "embedded" note (which is for seven words or less).  Content can  -->
<!-- contain the *internal* markup used here, such as "italic" or      -->
<!-- "bold", and that will be copied into the note for processing when -->
<!-- converted to braille                                              -->
<!--                                                                   -->
<!-- Template could be context-free for literal messages, but the      -->
<!-- $message will sometimes come from the context of an element       -->
<!-- (e.g. the "shortdescription" of an "image")                       -->
<xsl:template match="*" mode="transcriber-note">
    <xsl:param name="message"/>

    <segment indentation="7" runover="5">
        <!-- dot 4, dot 46, dot 126 -->
        <xsl:text>&#x2808;&#x2828;&#x2823;</xsl:text>
        <!-- *Copy* literal markup, or result of applying templates -->
        <xsl:copy-of select="$message"/>
        <!-- dot 4, dot 46, dot 345 -->
        <xsl:text>&#x2808;&#x2828;&#x281C;</xsl:text>
    </segment>
</xsl:template>

<!-- ############## -->
<!-- Invalid Source -->
<!-- ############## -->

<!-- Constructions that violate the PreTeXt schema receive an error   -->
<!-- message describing the violation, and leave a placeholder in the -->
<!-- output, rather than being accommodated.  Generated content       -->
<!-- (STACK static representations) is the known supplier: a "p"      -->
<!-- within a "p", an "image" within a "p", and "div" (an HTML        -->
<!-- element, not PreTeXt at all).                                    -->
<!--                                                                  -->
<!-- N.B. these templates are deliberately LAST in this stylesheet:   -->
<!-- a nested "p" can also match the display-splitting template for   -->
<!-- "p" at equal priority, and placement here settles the conflict   -->
<!-- in favor of the error.                                           -->
<xsl:template match="p/p|p/image|div">
    <xsl:message>PTX:ERROR:   the braille conversion has encountered source that is not valid PreTeXt (a "<xsl:value-of select="local-name()"/>" element within a "<xsl:value-of select="local-name(parent::*)"/>"); a placeholder appears in the output in its place</xsl:message>
    <xsl:text>[INVALID SOURCE]</xsl:text>
</xsl:template>

</xsl:stylesheet>
