<?xml version="1.0" encoding="utf-8"?> <!-- Inline code and code blocks (preformatted text, in HTML terms). TODO (2011-10-07): * Switch to listings for actual code. * Add an "inline-verbatim|verb" template for inline verbatim (which is what the "code" template does now). * Add "block-verbatim" as a match for "verbatim". --> <stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> <!-- Inline code. --> <template name="code" match="code"> <!-- Inline code. LaTeX uses listings to display this; delimiters for \lstinline are chosen automatically, depending on the contents. --> <common formats="/latex/xelatex/"> <xsl:text>\lstinline</xsl:text> <xsl:if test="@language"> <xsl:text>[language=</xsl:text> <xsl:value-of select="@language" /> <xsl:text>]</xsl:text> </xsl:if> <!-- We could just call choose-delimiter twice, but this avoids any possibility of weird corner cases where the second call returns a different delimiter from the first call. It's also slightly more efficient to only call the function once. --> <xsl:variable name="code-delimiter" select="infosci:choose-delimiter( node() )" /> <xsl:value-of select="$code-delimiter" /> <xsl:apply-templates /> <xsl:value-of select="$code-delimiter" /> </common> <common formats="/html/xhtml/"> <code><xsl:apply-templates /></code> </common> </template> <!-- Choose a valid delimiter for a LaTeX inline verbatim macro (e.g., \verb or \lstinline). "Valid" means that the delimiter can't occur in the source text. The function thus scans through a list of possible delimiters and looking for those that don't occur in the source text. $source-text: The source text to be wrapped inside a \verb macro. Returns: The function actually finds /all/ valid delimiters for the source text because of the effective parallel execution of xsl:for-each on sequences, but it only returns the first one found. If no valid delimiter can be found, the function raises an error and terminates the transformation. --> <function name="infosci:choose-delimiter" as="xs:string"> <common formats="/latex/xelatex/"> <xsl:param name="source-text" /> <xsl:variable name="valid-delimiters"> <!-- The LaTeX documentation says that you can use any character as a delimiter except * (because there is a \verb* form). To keep things simple, we've restricted the possible delimiters to punctuation that can be easily expressed in XML. --> <xsl:for-each select=" '`', '~', '!', '@', '#', '$', '%', '^', '(', ')', '-', '_', '=', '+', '[', ']', '{', '}', '\', '|', ';', ':', ',', '.', '/', '?'"> <xsl:if test="not( contains( $source-text, . ) )"> <xsl:value-of select = "." /> </xsl:if> </xsl:for-each> </xsl:variable> <!-- $valid-delimiters will be empty if none were found. --> <xsl:if test="string-length( $valid-delimiters ) = 0"> <xsl:message terminate="yes"> <xsl:text>ERROR: unable to determine a valid delimiter to use in \verb or \lstinline for the source text: </xsl:text> <xsl:value-of select="$source-text" /> </xsl:message> </xsl:if> <xsl:sequence select="substring( $valid-delimiters, 1, 1 )" /> </common> </function> <!-- Displayed code block. The LaTeX template uses the listings package. @allow-breaks: Whether or not to allow page breaks in the code block. 'yes' [default] 'no @language: Any language supported by the listings package in LaTeX. Has no effect in (X)HTML. --> <template name="code-block" match="code-block"> <common formats="/latex/xelatex/"> <xsl:call-template name="newline-internal" /> <!-- If the code-block specifies "allow-breaks='no'", wrap the code block inside a minipage to avoid page breaks within the code. --> <xsl:if test="@allow-breaks = 'no'"> <xsl:call-template name="newline-internal" /> <xsl:text>\begin{minipage}{\textwidth}</xsl:text> </xsl:if> <xsl:call-template name="newline-internal" /> <xsl:text>\begin{lstlisting}</xsl:text> <xsl:if test="@language"> <xsl:text>[language=</xsl:text> <xsl:value-of select="@language" /> <xsl:text>]</xsl:text> </xsl:if> <xsl:apply-templates /> <xsl:text>\end{lstlisting}</xsl:text> <xsl:call-template name="newline-internal" /> <xsl:if test="@allow-breaks = 'no'"> <xsl:text>\end{minipage}</xsl:text> <xsl:call-template name="newline-internal" /> </xsl:if> <xsl:call-template name="newline-internal" /> </common> <common formats="/html/xhtml/"> <pre class="code"><xsl:apply-templates /></pre> </common> </template> <!-- Inline verbatim text (as opposed to inline code). In LaTeX this equates to \verb; delimiters for this are chosen automatically, depending on the contents. --> <template name="inline-verbatim" match="inline-verbatim|verb"> <common formats="/latex/xelatex/"> <!-- We could just call choose-delimiter twice, but this avoids any possibility of weird corner cases where the second call returns a different delimiter from the first call. It's also slightly more efficient to only call the function once. --> <xsl:variable name="verb-delimiter" select="infosci:choose-delimiter( node() )" /> <xsl:value-of select="$verb-delimiter" /> <xsl:apply-templates /> <xsl:value-of select="$verb-delimiter" /> </common> <common formats="/html/xhtml/"> <code><xsl:apply-templates /></code> </common> </template> <!-- This is for stuff that should unequivocally be treated verbatim (e.g., problem code). --> <template name="verbatim" match="verbatim|block-verbatim"> <common formats="/latex/xelatex/"> <xsl:call-template name="newline-internal" /> <xsl:text>\begin{verbatim}</xsl:text> <xsl:call-template name="newline-internal" /> <xsl:apply-templates /> <xsl:call-template name="newline-internal" /> <xsl:text>\end{verbatim}</xsl:text> <xsl:call-template name="newline-internal" /> </common> <common formats="/html/xhtml/"> <pre><xsl:apply-templates /></pre> </common> </template> </stylesheet>