<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
xmlns:r="http://www.whitemagicsoftware.com/software/recipe"
xmlns:string="http://symphony-cms.com/functions"
xmlns:str="http://exslt.org/strings"
exclude-result-prefixes="r str string">
<xsl:import href="string-utilities.xsl" />
<xsl:import href="fractions.xsl" />
<xsl:output method="text" encoding="utf-8" />
<xsl:strip-space elements="*" />
<xsl:param name="preamble" select="''" />
<xsl:param name="recipe-toc" select="true()" />
<xsl:param name="ingredient-index" select="true()" />
<xsl:param name="book-copyright" select="true()" />
<xsl:param name="book-front-cover" select="true()" />
<xsl:param name="ebook" select="true()" />
<xsl:param name="page-photo-footer" select="false()" />
<xsl:param name="citation-style" select="'endcitations'" />
<xsl:key name="ingredient-id" match="/recipe-book/ingredients/ingredient" use="@id" />
<xsl:key name="recipe-by-category" match="recipe" use="tags/tag[1]" />
<xsl:variable name="punctuation">.,:;!?</xsl:variable>
<xsl:template match="/recipe-book">
<xsl:text>\documentclass</xsl:text>
<xsl:text>[</xsl:text>
<xsl:if test="not($ebook)">
<xsl:text>print,</xsl:text>
</xsl:if>
<xsl:if test="$page-photo-footer">
<xsl:text>fullpagepage-photo-footer,</xsl:text>
</xsl:if>
<xsl:value-of select="$citation-style"/>
<xsl:text>]</xsl:text>
<xsl:text>{recipe-book}
</xsl:text>
<xsl:text>\usepackage{hyperref}
</xsl:text>
<xsl:value-of select="$preamble" />
<xsl:text>\usepackage{imakeidx}
</xsl:text>
<xsl:text>\makeindex[intoc,name=flatingred]
</xsl:text>
<xsl:text>\makeindex[intoc,name=catingred]
</xsl:text>
<xsl:apply-templates select='book' />
<xsl:text>\begin{document}
</xsl:text>
<xsl:text>\frontmatter
</xsl:text>
<xsl:if test="$book-front-cover">
<xsl:text>\makecover</xsl:text>
<xsl:if test="$book-copyright">
<xsl:text>[copyrightpage]</xsl:text>
</xsl:if>
<xsl:text>
</xsl:text>
</xsl:if>
<xsl:apply-templates select="book/overview" mode="book-overview" />
<xsl:if test="$recipe-toc">
<xsl:text>\cleartoverso\tableofcontents*
</xsl:text>
</xsl:if>
<xsl:text>\mainmatter
</xsl:text>
<xsl:for-each select="recipe[count(. | key('recipe-by-category',tags/tag[1])[1]) = 1]">
<xsl:variable name="current-grouping-key" select="tags/tag[1]"/>
<xsl:if test="$current-grouping-key != ''">
<xsl:text>
\recipecategory{</xsl:text>
<xsl:apply-templates select="$current-grouping-key" mode="escape-capitalize"/>
<xsl:text>}

</xsl:text>
<xsl:variable name="current-group"
select="key('recipe-by-category', $current-grouping-key)" />
<xsl:for-each select="$current-group">
<xsl:apply-templates select="." />
</xsl:for-each>
</xsl:if>
</xsl:for-each>
<xsl:if test="recipe[tags/tag = '' or not(tags/tag)]">
<xsl:text>
\recipecategory{Recipes}

</xsl:text>
<xsl:apply-templates select="recipe[tags/tag = '' or not(tags/tag)]" />
</xsl:if>
<xsl:text>\backmatter
</xsl:text>
<xsl:text>\renewcommand{\clearforchapter}{\newpage}
</xsl:text>
<xsl:if test="$ingredient-index">
<xsl:text>\renewcommand{\indexname}{Alphabetized Ingredients}
</xsl:text>
<xsl:text>\printindex[flatingred]
</xsl:text>
<xsl:text>\renewcommand{\indexname}{Categorized Ingredients}
</xsl:text>
<xsl:text>\reduceindexindent
</xsl:text>
<xsl:text>\printindex[catingred]
</xsl:text>
</xsl:if>
<xsl:text>\end{document}
</xsl:text>
</xsl:template>
<xsl:template match="book">
<xsl:text>\title{</xsl:text>
<xsl:apply-templates select="title" mode="escape-capitalize" />
<xsl:text>}
</xsl:text>
<xsl:text>\date{</xsl:text>
<xsl:apply-templates select="created" mode="escape-capitalize" />
<xsl:text>}
</xsl:text>
<xsl:text>\author{</xsl:text>
<xsl:apply-templates select="author" mode="escape-capitalize" />
<xsl:text>}
</xsl:text>
<xsl:apply-templates select="photo" mode="book" />
</xsl:template>
<xsl:template match="overview" mode="book-overview">
<xsl:text>
\begin{overview}{</xsl:text>
<xsl:apply-templates select="@label" mode="escape-capitalize" />
<xsl:text>}
</xsl:text>
<xsl:if test="../photo[@use='overview']">
<xsl:apply-templates select="../photo[@use='overview']/uri" mode="book-overview"/>
</xsl:if>
<xsl:apply-templates select="p" />
<xsl:text>\end{overview}

</xsl:text>
</xsl:template>
<xsl:template match="p">
<xsl:apply-templates mode="escape" />
<xsl:text>

</xsl:text>
</xsl:template>
<xsl:template match="recipe">
<xsl:if test="description/photo[@use='one-page' or @use='two-page']">
<xsl:text>\checkfiller
</xsl:text>
</xsl:if>
<xsl:if test="description/photo[@use='two-page']">
<xsl:text>\preparespread
</xsl:text>
</xsl:if>
<xsl:text>\begin{recipe}</xsl:text>
<xsl:apply-templates select="description/citation[descendant::*]" />
<xsl:text>{</xsl:text>
<xsl:apply-templates select="description/title" />
<xsl:text>}
</xsl:text>
<xsl:apply-templates select="description/photo[@use='recipe-inset']" mode="recipe" />
<xsl:apply-templates />
<xsl:apply-templates select="description/photo[@use='one-page' or @use='two-page']" mode="recipe" />
<xsl:text>\end{recipe}

</xsl:text>
<xsl:if test="description/photo[@use='two-page']">
<xsl:text>\cancelspread
</xsl:text>
</xsl:if>
</xsl:template>
<xsl:template match="photo[@use='front-cover']" mode="book">
<xsl:apply-templates select="uri" mode="book" />
</xsl:template>
<xsl:template match="photo[@use='overview']" mode="book" />
<xsl:template match="photo" mode="recipe">
<xsl:text>\photo[embed=</xsl:text>
<xsl:choose>
<xsl:when test="@use='recipe-inset'">
<xsl:text>inset</xsl:text>
</xsl:when>
<xsl:when test="@use='one-page'">
<xsl:text>fullpage</xsl:text>
</xsl:when>
<xsl:when test="@use='two-page'">
<xsl:text>twopagespread</xsl:text>
</xsl:when>
</xsl:choose>
<xsl:text>,</xsl:text>
<xsl:apply-templates match="citation[descendant::*]" />
<xsl:text>]{</xsl:text>
<xsl:apply-templates select="uri" mode="escape"/>
<xsl:text>}
</xsl:text>
</xsl:template>
<xsl:template match="uri" mode="book-overview">
<xsl:text>\begin{wrapfigure}{l}{.45\textwidth}
</xsl:text>
<xsl:text>\insetphoto[</xsl:text>
<xsl:apply-templates select="following-sibling::citation[descendant::*]" />
<xsl:text>]{</xsl:text>
<xsl:apply-templates />
<xsl:text>}
</xsl:text>
<xsl:text>\end{wrapfigure}

</xsl:text>
</xsl:template>
<xsl:template match="uri" mode="book">
<xsl:if test="$book-front-cover">
<xsl:text>\frontcoverphoto[</xsl:text>
<xsl:apply-templates select="following-sibling::citation[descendant::*]" />
<xsl:text>]{</xsl:text>
<xsl:apply-templates />
<xsl:text>}
</xsl:text>
</xsl:if>
</xsl:template>
<xsl:template match="citation[descendant::*]">
<xsl:if test="author">
<xsl:text>author={</xsl:text>
<xsl:apply-templates select="author" mode="escape" />
<xsl:text>},</xsl:text>
</xsl:if>
<xsl:if test="author/@url">
<xsl:text>authorurl={</xsl:text>
<xsl:apply-templates select="author/@url" mode="escape" />
<xsl:text>},</xsl:text>
</xsl:if>
<xsl:if test="license">
<xsl:text>license={</xsl:text>
<xsl:apply-templates select="license" mode="escape" />
<xsl:text>},</xsl:text>
</xsl:if>
<xsl:if test="license/@url">
<xsl:text>licenseurl={</xsl:text>
<xsl:apply-templates select="license/@url" mode="escape" />
<xsl:text>},</xsl:text>
</xsl:if>
</xsl:template>
<xsl:template match="description/title">
<xsl:apply-templates mode="escape-capitalize" />
</xsl:template>
<xsl:template match="preparation">
<xsl:apply-templates />
</xsl:template>
<xsl:template match="oven">
<xsl:text>\oven{</xsl:text>
<xsl:value-of select="@temperature" />
<xsl:text>\,</xsl:text>
<xsl:choose>
<xsl:when test="@unit='C' or @unit='F'">
<xsl:text>\textdegree </xsl:text>
</xsl:when>
</xsl:choose>
<xsl:value-of select="@unit" />
<xsl:text>}

</xsl:text>
</xsl:template>
<xsl:template match="equipment[descendant::text()]">
<xsl:text>\begin{equipment}
</xsl:text>
<xsl:for-each select="*[child::*]">
<xsl:text> \item[</xsl:text>
<xsl:call-template name="escape-capitalize">
<xsl:with-param name="ec" select="name()" />
</xsl:call-template>
<xsl:text>] </xsl:text>
<xsl:call-template name="escape-capitalize-oxfordcomma">
<xsl:with-param name="itemlist" select="object" />
</xsl:call-template>
<xsl:text>
</xsl:text>
</xsl:for-each>
<xsl:text>\end{equipment}

</xsl:text>
</xsl:template>
<xsl:template name="escape-capitalize-oxfordcomma">
<xsl:param name="itemlist" />
<xsl:variable name="itemcount" select="count($itemlist)" />
<xsl:variable name="items">
<xsl:for-each select="$itemlist">
<xsl:choose>
<xsl:when test="$itemcount > 2">
<xsl:choose>
<xsl:when test="position()=1">
<xsl:value-of select="concat(' ', ., ',')"/>
</xsl:when>
<xsl:when test="position()=last()">
<xsl:value-of select="concat(' and ', .)"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="concat(' ', .,',')"/>
</xsl:otherwise>
</xsl:choose>
</xsl:when>
<xsl:when test="$itemcount = 2">
<xsl:choose>
<xsl:when test="position()=1">
<xsl:value-of select="concat(' ', .,' and')"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="concat(' ', .)"/>
</xsl:otherwise>
</xsl:choose>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="concat(' ', .)"/>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</xsl:variable>
<xsl:call-template name="escape">
<xsl:with-param
name="e" select="string:capitalize(normalize-space($items))" />
</xsl:call-template>
</xsl:template>
<xsl:template match="@label">
<xsl:text>[</xsl:text>
<xsl:call-template name="escape-capitalize">
<xsl:with-param name="ec" select="." />
</xsl:call-template>
<xsl:text>]</xsl:text>
<xsl:text>
</xsl:text>
</xsl:template>
<xsl:template match="ingredients[parent::recipe]">
<xsl:if test="count(ingredient[not(@substitute) or @substitute='']) > 0">
<xsl:text>\begin{ingredients}
</xsl:text>
<xsl:apply-templates select="@label" />
<xsl:apply-templates select="ingredient[not(@substitute) or @substitute='']" />
<xsl:text>\end{ingredients}

</xsl:text>
</xsl:if>
<xsl:if test="ingredient[@condition != '']">
<xsl:text>\begin{preparation}
</xsl:text>
<xsl:apply-templates select="ingredient[@condition != '']" mode="prep" />
<xsl:text>\end{preparation}
</xsl:text>
</xsl:if>
<xsl:if test="ingredient[@substitute != '']">
<xsl:text>\begin{substitution}
</xsl:text>
<xsl:apply-templates select="ingredient[@substitute != '']" mode="subst" />
<xsl:text>\end{substitution}
</xsl:text>
</xsl:if>
</xsl:template>
<xsl:template match="ingredient">
<xsl:text> \ingred{</xsl:text>
<xsl:call-template name="utf-fraction">
<xsl:with-param name="quantity" select="@min-quantity" />
</xsl:call-template>
<xsl:if test="@max-quantity">
<xsl:text>--</xsl:text>
<xsl:call-template name="utf-fraction">
<xsl:with-param name="quantity" select="@max-quantity" />
</xsl:call-template>
</xsl:if>
<xsl:text>}{</xsl:text>
<xsl:value-of select="@unit" />
<xsl:text>}{</xsl:text>
<xsl:apply-templates select="key('ingredient-id', @id)/@name" />
<xsl:text>}%
</xsl:text>
<xsl:if test="key('ingredient-id',@id)/categories/category">
<xsl:for-each select="key('ingredient-id',@id)/categories/category">
<xsl:text> \index[catingred]{</xsl:text>
<xsl:call-template name="replace">
<xsl:with-param name="pText" select="@name" />
<xsl:with-param name="pToken" select="','" />
<xsl:with-param name="pSubst" select="'!'" />
</xsl:call-template>
<xsl:text>!</xsl:text>
<xsl:apply-templates select="../../@name" />
<xsl:text>}%
</xsl:text>
</xsl:for-each>
</xsl:if>
<xsl:text> \index[flatingred]{</xsl:text>
<xsl:apply-templates select="key('ingredient-id', @id)/@name" />
<xsl:text>!</xsl:text>
<xsl:apply-templates select="ancestor::recipe/description/title" />
<xsl:text>}%
</xsl:text>
</xsl:template>
<xsl:template match="ingredient[@condition != '']" mode="prep">
<xsl:for-each select=".">
<xsl:text>\item </xsl:text>
<xsl:apply-templates select="@condition" mode="prep" />
<xsl:text> the </xsl:text>
<xsl:apply-templates select="key('ingredient-id', @id)/@name" />
<xsl:text>.
</xsl:text>
</xsl:for-each>
</xsl:template>
<xsl:template match="ingredient[@substitute != '']" mode="subst">
<xsl:text> \item </xsl:text>
<xsl:call-template name="utf-fraction">
<xsl:with-param name="quantity" select="@min-quantity" />
</xsl:call-template>
<xsl:if test="@max-quantity">
<xsl:text>--</xsl:text>
<xsl:call-template name="utf-fraction">
<xsl:with-param name="quantity" select="@max-quantity" />
</xsl:call-template>
</xsl:if>
<xsl:text> </xsl:text>
<xsl:value-of select="@unit" />
<xsl:text> </xsl:text>
<xsl:apply-templates select="key('ingredient-id', @id)/@name" />
<xsl:text> for </xsl:text>
<xsl:apply-templates select="key('ingredient-id', @substitute)/@name" />
<xsl:text>
</xsl:text>
<xsl:if test="key('ingredient-id',@id)/categories/category">
<xsl:for-each select="key('ingredient-id',@id)/categories/category">
<xsl:text> \index[catingred]{</xsl:text>
<xsl:call-template name="replace">
<xsl:with-param name="pText" select="@name" />
<xsl:with-param name="pToken" select="','" />
<xsl:with-param name="pSubst" select="'!'" />
</xsl:call-template>
<xsl:text>!</xsl:text>
<xsl:apply-templates select="../../@name" />
<xsl:text>}%
</xsl:text>
</xsl:for-each>
</xsl:if>
<xsl:text> \index[flatingred]{</xsl:text>
<xsl:apply-templates select="key('ingredient-id', @id)/@name" />
<xsl:text>!</xsl:text>
<xsl:apply-templates select="ancestor::recipe/description/title" />
<xsl:text>}%
</xsl:text>
</xsl:template>
<xsl:template match="@condition" mode="prep">
<xsl:variable name="actions" select="str:tokenize( ., ',' )" />
<xsl:variable name="tokens" select="count( $actions )" />
<xsl:variable name="condition">
<xsl:for-each select="$actions">
<xsl:choose>
<xsl:when test="$tokens > 2">
<xsl:choose>
<xsl:when test="position()=1">
<xsl:value-of select="concat(' ', ., ',')"/>
</xsl:when>
<xsl:when test="position()=last()">
<xsl:value-of select="concat(' and ', .)"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="concat(' ', .,',')"/>
</xsl:otherwise>
</xsl:choose>
</xsl:when>
<xsl:when test="$tokens = 2">
<xsl:choose>
<xsl:when test="position()=1">
<xsl:value-of select="concat(' ', .,' and')"/>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="concat(' ', .)"/>
</xsl:otherwise>
</xsl:choose>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="concat(' ', .)"/>
</xsl:otherwise>
</xsl:choose>
</xsl:for-each>
</xsl:variable>
<xsl:call-template name="escape">
<xsl:with-param
name="e" select="string:capitalize(normalize-space($condition))" />
</xsl:call-template>
</xsl:template>
<xsl:template name="replace">
<xsl:param name="pText"/>
<xsl:param name="pToken"/>
<xsl:param name="pSubst" />
<xsl:choose>
<xsl:when test="string-length($pText) = 0" />
<xsl:when test="contains($pText, $pToken)">
<xsl:value-of select="substring-before($pText, $pToken)"/>
<xsl:value-of select="$pSubst"/>
<xsl:call-template name="replace">
<xsl:with-param name="pText" select="substring-after($pText, $pToken)"/>
<xsl:with-param name="pToken" select="$pToken"/>
<xsl:with-param name="pSubst" select="$pSubst" />
</xsl:call-template>
</xsl:when>
<xsl:otherwise>
<xsl:value-of select="$pText"/>
</xsl:otherwise>
</xsl:choose>
</xsl:template>
<xsl:template match="directions[descendant::text() or @label != '']">
<xsl:if test="not(preceding-sibling::directions)">
<xsl:text>\startinstructions

</xsl:text>
</xsl:if>
<xsl:text>\begin{instructions}
</xsl:text>
<xsl:apply-templates select="@label" />
<xsl:apply-templates select="step" />
<xsl:if test="not(step)">
<xsl:text>\item Serve!</xsl:text>
</xsl:if>
<xsl:text>\end{instructions}

</xsl:text>
</xsl:template>
<xsl:template match="step">
<xsl:text> \item </xsl:text>
<xsl:value-of select="normalize-space(string:capitalize(@action))" />
<xsl:if test="not(contains($punctuation,substring(normalize-space(text()),1,1)))"><xsl:text> </xsl:text></xsl:if>
<xsl:apply-templates mode="escape" />
<xsl:text>.
</xsl:text>
</xsl:template>
<xsl:template name="escape">
<xsl:param name="e" />
<xsl:call-template name="replace">
<xsl:with-param name="pText" select="$e" />
<xsl:with-param name="pToken" select="'&'" />
<xsl:with-param name="pSubst" select="'\&'" />
</xsl:call-template>
</xsl:template>
<xsl:template name="escape-capitalize">
<xsl:param name="ec" />
<xsl:variable name="escaped">
<xsl:call-template name="escape">
<xsl:with-param name="e" select="$ec" />
</xsl:call-template>
</xsl:variable>
<xsl:value-of select="normalize-space(string:capitalize-words($escaped))" />
</xsl:template>
<xsl:template match="text()" mode="escape">
<xsl:call-template name="escape">
<xsl:with-param name="e" select="." />
</xsl:call-template>
</xsl:template>
<xsl:template match="text()" mode="escape-capitalize">
<xsl:call-template name="escape-capitalize">
<xsl:with-param name="ec" select="." />
</xsl:call-template>
</xsl:template>
<xsl:template match="*" />
</xsl:stylesheet>