Newer
Older
XML / modules / code-formatting.xml
nstanger on 23 Feb 2012 5 KB - Updated some documentation.
<?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>