[Tynstep-svn] r188 - in trunk/step: step-core/src/main/java/com/tyndalehouse/step/core step-core/src/main/java/com/tyndalehouse/step/core/utils step-core/src/main/java/com/tyndalehouse/step/core/xsl step-core/src/main/java/com/tyndalehouse/step/core/xsl/impl step-core/src/main/resources step-core/src/main/resources/com/tyndalehouse/step/core/service/impl step-core/src/test/java/com/tyndalehouse/step/core step-core/src/test/java/com/tyndalehouse/step/core/service step-core/src/test/java/com/tyndalehouse/step/core/utils step-parent step-web/src/main/webapp step-web/src/main/webapp/css step-web/src/main/webapp/js

ChrisBurrell at crosswire.org ChrisBurrell at crosswire.org
Sun Nov 21 14:46:25 MST 2010


Author: ChrisBurrell
Date: 2010-11-21 14:46:24 -0700 (Sun, 21 Nov 2010)
New Revision: 188

Added:
   trunk/step/step-core/src/main/java/com/tyndalehouse/step/core/utils/
   trunk/step/step-core/src/main/java/com/tyndalehouse/step/core/utils/StringConversionUtils.java
   trunk/step/step-core/src/main/java/com/tyndalehouse/step/core/utils/XslHelper.java
   trunk/step/step-core/src/main/java/com/tyndalehouse/step/core/xsl/MultiInterlinearProvider.java
   trunk/step/step-core/src/main/java/com/tyndalehouse/step/core/xsl/impl/MultiInterlinearProviderImpl.java
   trunk/step/step-core/src/main/resources/com/tyndalehouse/step/core/service/impl/old_interlinear.xsl
   trunk/step/step-core/src/main/resources/log4j.properties
   trunk/step/step-core/src/test/java/com/tyndalehouse/step/core/utils/
   trunk/step/step-core/src/test/java/com/tyndalehouse/step/core/utils/StringConversionUtilsTest.java
Modified:
   trunk/step/step-core/src/main/java/com/tyndalehouse/step/core/xsl/impl/InterlinearProviderImpl.java
   trunk/step/step-core/src/main/resources/com/tyndalehouse/step/core/service/impl/interlinear.xsl
   trunk/step/step-core/src/test/java/com/tyndalehouse/step/core/service/JSwordServiceImplTest.java
   trunk/step/step-parent/pom.xml
   trunk/step/step-web/src/main/webapp/css/initial-fonts.css
   trunk/step/step-web/src/main/webapp/css/initial-layout.css
   trunk/step/step-web/src/main/webapp/css/passage.css
   trunk/step/step-web/src/main/webapp/index.jsp
   trunk/step/step-web/src/main/webapp/js/bookmark.js
   trunk/step/step-web/src/main/webapp/js/init.js
   trunk/step/step-web/src/main/webapp/js/passage.js
   trunk/step/step-web/src/main/webapp/js/passage_toolbar.js
   trunk/step/step-web/src/main/webapp/js/util.js
Log:


Added: trunk/step/step-core/src/main/java/com/tyndalehouse/step/core/utils/StringConversionUtils.java
===================================================================
--- trunk/step/step-core/src/main/java/com/tyndalehouse/step/core/utils/StringConversionUtils.java	                        (rev 0)
+++ trunk/step/step-core/src/main/java/com/tyndalehouse/step/core/utils/StringConversionUtils.java	2010-11-21 21:46:24 UTC (rev 188)
@@ -0,0 +1,73 @@
+package com.tyndalehouse.step.core.utils;
+
+/**
+ * A collection of utility methods enabling us to convert Strings, references one way or another.
+ * 
+ * @author Chris
+ */
+public final class StringConversionUtils {
+    private static final char KEY_SEPARATOR = ':';
+    private static final String STRONG_PREFIX = "strong:";
+    private static final int LANGUAGE_INDICATOR = STRONG_PREFIX.length();
+
+    /**
+     * hiding implementation
+     */
+    private StringConversionUtils() {
+        // hiding implementation
+    }
+
+    /**
+     * Not all bibles encode strong numbers as strong:[HG]\d+ unfortunately, so instead we cope for strong: and
+     * strong:H.
+     * 
+     * In essence we chop off any of the following prefixes: strong:G, strong:H, strong:, H, G. We don't use a regularl
+     * expression, since this will be much quicker
+     * 
+     * @param strong strong key
+     * @return the key containing just the digits
+     */
+    public static String getStrongKey(final String strong) {
+        if (strong.startsWith(STRONG_PREFIX)) {
+            final char c = strong.charAt(LANGUAGE_INDICATOR);
+            if (c == 'H' || c == 'G') {
+                return strong.substring(LANGUAGE_INDICATOR + 1);
+            }
+            return strong.substring(LANGUAGE_INDICATOR);
+        }
+
+        final char c = strong.charAt(0);
+        if (c == 'H' || c == 'G') {
+            return strong.substring(1);
+        }
+
+        // perhaps some passages encode just the number
+        return strong;
+    }
+
+    /**
+     * in this case, we assume that a key starts shortly after the last ':' with a number
+     * 
+     * @param potentialKey a key that can potentially be shortened
+     * @return the shortened key
+     */
+    public static String getAnyKey(final String potentialKey) {
+        // find first colon and start afterwards, -1 yields 0, which is the beginning of the string
+        // so we can work with that.
+        int start = potentialKey.lastIndexOf(KEY_SEPARATOR) + 1;
+
+        // start at the first char after the colon
+        // int start = lastColon + 1;
+        final char protocol = potentialKey.charAt(start);
+        if (protocol == 'G' || protocol == 'H') {
+            start++;
+        }
+
+        // finally, we may have 0s:
+        while (potentialKey.charAt(start) == '0') {
+            start++;
+        }
+
+        return potentialKey.substring(start);
+    }
+}

Added: trunk/step/step-core/src/main/java/com/tyndalehouse/step/core/utils/XslHelper.java
===================================================================
--- trunk/step/step-core/src/main/java/com/tyndalehouse/step/core/utils/XslHelper.java	                        (rev 0)
+++ trunk/step/step-core/src/main/java/com/tyndalehouse/step/core/utils/XslHelper.java	2010-11-21 21:46:24 UTC (rev 188)
@@ -0,0 +1,58 @@
+package com.tyndalehouse.step.core.utils;
+
+import static com.tyndalehouse.step.core.utils.StringConversionUtils.getAnyKey;
+import static java.lang.String.format;
+import static org.apache.commons.lang.StringUtils.split;
+
+public final class XslHelper {
+    private static final int APPROXIMATE_ANCHOR_LENGTH = 56;
+    private static final int APPROXIMATE_SPAN_LENGTH = 46;
+    private static final String START_ANCHOR = "<a href=\"";
+    private static final String START_FUNCTION_WRAPPER = "('";
+    private static final String END_FUNCTION_WRAPPER = "')";
+    private static final String QUOTED_END_TAG = "\">";
+    private static final String END_ANCHOR = "</a>";
+    private static final String SEPARATORS = " |";
+    private static final String BLANK_SPACE = "&nbsp;";
+
+    /**
+     * hiding implementation
+     */
+    private XslHelper() {
+        // hiding implementation
+    }
+
+    /**
+     * returns a "span" element for use in an HTML document
+     * 
+     * @param strongsText the key straight from the OSIS text
+     * @return a span containing all the strongs, seperated by spaces
+     */
+    public static String getSpanFromAttributeName(final String strongsText, final String functionCall) {
+        final String[] strongs = split(strongsText, SEPARATORS);
+        if (strongs == null || strongs.length == 0) {
+            return format(XslHelper.BLANK_SPACE);
+        }
+
+        // we transform each strong to something like: "<a href=\"%s\">%s</a>";
+        final StringBuilder sb = new StringBuilder(APPROXIMATE_SPAN_LENGTH + strongs.length * APPROXIMATE_ANCHOR_LENGTH);
+
+        String strongKey;
+        for (int ii = 0; ii < strongs.length; ii++) {
+            strongKey = getAnyKey(strongs[ii]);
+            sb.append(START_ANCHOR);
+            sb.append(functionCall);
+            sb.append(START_FUNCTION_WRAPPER);
+            sb.append(strongKey);
+            sb.append(END_FUNCTION_WRAPPER);
+            sb.append(QUOTED_END_TAG);
+            sb.append(strongKey);
+            sb.append(END_ANCHOR);
+
+            if (ii + 1 != strongs.length) {
+                sb.append(' ');
+            }
+        }
+        return sb.toString();
+    }
+}

Added: trunk/step/step-core/src/main/java/com/tyndalehouse/step/core/xsl/MultiInterlinearProvider.java
===================================================================
--- trunk/step/step-core/src/main/java/com/tyndalehouse/step/core/xsl/MultiInterlinearProvider.java	                        (rev 0)
+++ trunk/step/step-core/src/main/java/com/tyndalehouse/step/core/xsl/MultiInterlinearProvider.java	2010-11-21 21:46:24 UTC (rev 188)
@@ -0,0 +1,14 @@
+package com.tyndalehouse.step.core.xsl;
+
+public interface MultiInterlinearProvider {
+    /**
+     * This is the more specific method
+     * 
+     * @param version the version requested
+     * @param verseNumber helps locate the word by adding location awareness
+     * @param strong identifies the word by its root in the original language
+     * @param morph identifies the morphology of the word (i.e. the grammar)
+     * @return the word in the original language (Greek, Hebrew, etc.)
+     */
+    String getWord(String version, String verseNumber, String strong, String morph);
+}

Modified: trunk/step/step-core/src/main/java/com/tyndalehouse/step/core/xsl/impl/InterlinearProviderImpl.java
===================================================================
--- trunk/step/step-core/src/main/java/com/tyndalehouse/step/core/xsl/impl/InterlinearProviderImpl.java	2010-11-15 20:29:03 UTC (rev 187)
+++ trunk/step/step-core/src/main/java/com/tyndalehouse/step/core/xsl/impl/InterlinearProviderImpl.java	2010-11-21 21:46:24 UTC (rev 188)
@@ -1,5 +1,7 @@
 package com.tyndalehouse.step.core.xsl.impl;
 
+import static com.tyndalehouse.step.core.utils.StringConversionUtils.getAnyKey;
+import static com.tyndalehouse.step.core.utils.StringConversionUtils.getStrongKey;
 import static org.apache.commons.lang.StringUtils.isBlank;
 import static org.apache.commons.lang.StringUtils.isNotBlank;
 import static org.apache.commons.lang.StringUtils.split;
@@ -37,10 +39,6 @@
  * 
  */
 public class InterlinearProviderImpl implements InterlinearProvider {
-    /**
-     * set of characters used to distinguish one strong from another
-     */
-    private static final String STRONG_SEPARATORS = " []";
 
     /**
      * bestAccuracy gives a word by its dual key (strong,morph)
@@ -100,28 +98,18 @@
 
         // the keys passed in may have multiple references and morphologies, therefore, we need to lookup
         // multiple items.
+        final String[] strongs = split(strong);
+        final String[] morphs = morph == null ? new String[0] : split(morph);
 
-        // ///////////////////////////
-        // TODO we need to remove the strong:[G/H] from the string, since some versions don't have it
-        // and key things differently
-        // ////////////////////////////
-        final String[] strongs = split(strong, STRONG_SEPARATORS);
-        final String[] morphs = split(morph, STRONG_SEPARATORS);
-
-        // if we have no morphs, then might as well call getWord(verseNumber, strong) straight away
-        if (morphs == null || morphs.length == 0) {
-            results.add(getWord(verseNumber, strong));
-            return convertToString(results);
-        }
-
         // There are at most strongs.length words, and we might have morphological data to help
         for (final String s : strongs) {
             boolean foundMatchForStrong = false;
+            final String strongKey = getAnyKey(s);
 
-            // each could be using the morphs we have, so try them all
+            // each could be using the morphs we have, so try them all - this gets skipped if we have no morphs
             for (final String m : morphs) {
                 // lookup (strong,morph) -> word first
-                final DualKey<String, String> key = new DualKey<String, String>(s, m);
+                final DualKey<String, String> key = new DualKey<String, String>(getStrongKey(strongKey), m);
                 final String word = this.bestAccuracy.get(key);
 
                 if (word != null) {
@@ -132,7 +120,7 @@
 
             // have we found a match? if not, we better try and find one using the verse
             if (!foundMatchForStrong) {
-                results.add(getWord(verseNumber, strong));
+                results.add(getWord(verseNumber, strongKey));
             }
         }
 
@@ -143,7 +131,7 @@
      * Takes a set, and outputs the strings concatenated together (and separated by a space.
      * 
      * @param results the results that should be converted to a string
-     * @return
+     * @return a String containing results to be displayed
      */
     private String convertToString(final Set<String> results) {
         final Iterator<String> iterator = results.iterator();
@@ -245,14 +233,9 @@
         // comparing against other OSIS XML texts which should be formatted in the same way!
         // however, some attributes may contain multiple strongs and morphs tagged to one word.
         // therefore we do need to split the text.
-        final String[] strongs = split(strong, STRONG_SEPARATORS);
-        final String[] morphs = split(morph, STRONG_SEPARATORS);
+        final String[] strongs = split(strong);
+        final String[] morphs = split(morph);
 
-        // ///////////////////////////
-        // TODO we need to remove the strong:[G/H] from the string, since some versions don't have it
-        // and key things differently
-        // ////////////////////////////
-
         if (strongs == null) {
             return;
         }
@@ -290,13 +273,14 @@
      * @param word the word to be stored
      */
     void addTextualInfo(final String verseReference, final String strong, final String morph, final String word) {
+        final String strongKey = getAnyKey(strong);
 
-        if (isNotBlank(strong) && isNotBlank(morph)) {
-            final DualKey<String, String> strongMorphKey = new DualKey<String, String>(strong, morph);
+        if (isNotBlank(strongKey) && isNotBlank(morph)) {
+            final DualKey<String, String> strongMorphKey = new DualKey<String, String>(strongKey, morph);
             this.bestAccuracy.put(strongMorphKey, word);
         }
 
-        final DualKey<String, String> strongVerseKey = new DualKey<String, String>(strong, verseReference);
+        final DualKey<String, String> strongVerseKey = new DualKey<String, String>(strongKey, verseReference);
 
         List<String> verseKeyedStrongs = this.limitedAccuracy.get(strongVerseKey);
         if (verseKeyedStrongs == null) {
@@ -306,6 +290,6 @@
         verseKeyedStrongs.add(word);
 
         // finally add it to the worst accuracy - i.e. just based on strongs (could probably refactor)
-        this.worstAccuracy.put(strong, word);
+        this.worstAccuracy.put(strongKey, word);
     }
 }

Added: trunk/step/step-core/src/main/java/com/tyndalehouse/step/core/xsl/impl/MultiInterlinearProviderImpl.java
===================================================================
--- trunk/step/step-core/src/main/java/com/tyndalehouse/step/core/xsl/impl/MultiInterlinearProviderImpl.java	                        (rev 0)
+++ trunk/step/step-core/src/main/java/com/tyndalehouse/step/core/xsl/impl/MultiInterlinearProviderImpl.java	2010-11-21 21:46:24 UTC (rev 188)
@@ -0,0 +1,46 @@
+package com.tyndalehouse.step.core.xsl.impl;
+
+import static org.apache.commons.lang.StringUtils.isBlank;
+import static org.apache.commons.lang.StringUtils.split;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import com.tyndalehouse.step.core.xsl.InterlinearProvider;
+import com.tyndalehouse.step.core.xsl.MultiInterlinearProvider;
+
+/**
+ * This implementation will support multiple versions, so each of the methods is keyed by version requested.
+ * 
+ * @author Chris
+ * 
+ */
+public class MultiInterlinearProviderImpl implements MultiInterlinearProvider {
+    /** we separate by commas and spaces */
+    private static final String VERSION_SEPARATOR = ", ";
+    Map<String, InterlinearProvider> interlinearProviders = new HashMap<String, InterlinearProvider>();
+
+    /**
+     * sets up the interlinear provider with the correct version and text scope.
+     * 
+     * @param version the version to use to set up the interlinear
+     * @param textScope the text scope reference, defining the bounds of the lookup
+     */
+    public MultiInterlinearProviderImpl(final String versions, final String textScope) {
+        // first check whether the values passed in are correct
+        if (isBlank(versions) || isBlank(textScope)) {
+            return;
+        }
+
+        final String[] differentVersions = split(versions, VERSION_SEPARATOR);
+        if (differentVersions != null) {
+            for (final String version : differentVersions) {
+                this.interlinearProviders.put(version, new InterlinearProviderImpl(version, textScope));
+            }
+        }
+    }
+
+    public String getWord(final String version, final String verseNumber, final String strong, final String morph) {
+        return this.interlinearProviders.get(version).getWord(verseNumber, strong, morph);
+    }
+}

Modified: trunk/step/step-core/src/main/resources/com/tyndalehouse/step/core/service/impl/interlinear.xsl
===================================================================
--- trunk/step/step-core/src/main/resources/com/tyndalehouse/step/core/service/impl/interlinear.xsl	2010-11-15 20:29:03 UTC (rev 187)
+++ trunk/step/step-core/src/main/resources/com/tyndalehouse/step/core/service/impl/interlinear.xsl	2010-11-21 21:46:24 UTC (rev 188)
@@ -21,7 +21,7 @@
  * ID: $Id: default.xsl 1943 2009-03-25 11:43:28Z dmsmith $
  -->
  <!--
- * Transforms OSIS to HTML for viewing within JSword browsers.
+ * Transforms OSIS to HTML for viewing within Web browsers.
  * Note: There are custom protocols which the browser must handle.
  * 
  * @see gnu.lgpl.License for license details.
@@ -49,12 +49,6 @@
        but font does not. Therefore we use font as a span.
     -->
   <!-- gdef and hdef refer to hebrew and greek definitions keyed by strongs -->
-  <xsl:param name="greek.def.protocol" select="'gdef:'"/>
-  <xsl:param name="hebrew.def.protocol" select="'hdef:'"/>
-  <xsl:param name="lex.def.protocol" select="'lex:'"/>
-  <!-- currently these are not used, but they are for morphologic forms -->
-  <xsl:param name="greek.morph.protocol" select="'gmorph:'"/>
-  <xsl:param name="hebrew.morph.protocol" select="'hmorph:'"/>
 
   <!-- The absolute base for relative references. -->
   <xsl:param name="baseURL" select="''"/>
@@ -96,7 +90,10 @@
   <xsl:param name="direction" select="'ltr'"/>
 
   <!-- Whether to show an interlinear and the provider helping with the lookup -->
-  <xsl:param name="Interlinear" select="'false'" />
+  <xsl:param name="strongFunctionCall" select="'javascript:showStrong'" />
+  <xsl:param name="morphFunctionCall" select="'javascript:showMorph'" />
+  
+  <!--  a comma separated list of versions to display, if provided, then we display the interlinear -->
   <xsl:param name="interlinearVersion" select="''" />
   <xsl:param name="interlinearReference" select="''" />
 
@@ -106,7 +103,7 @@
   <xsl:variable name="shaper" select="jsword:org.crosswire.common.icu.NumberShaper.new()"/>
   
   <!--  set up interlinear provider, if we have requested it -->
-  <xsl:variable name="interlinearProvider" select="jsword:com.tyndalehouse.step.core.xsl.impl.InterlinearProviderImpl.new(string($interlinearVersion), string($interlinearReference))" />
+  <xsl:variable name="interlinearProvider" select="jsword:com.tyndalehouse.step.core.xsl.impl.MultiInterlinearProviderImpl.new(string($interlinearVersion), string($interlinearReference))" />
 
   <!--=======================================================================-->
   <xsl:template match="/">
@@ -465,220 +462,103 @@
   </xsl:template>
 
   <!--=======================================================================-->
-  <xsl:template match="w">
-    <!-- Output the content followed by all the lemmas and then all the morphs. -->
-    <xsl:variable name="innerWordText"><xsl:apply-templates/></xsl:variable>
-    <xsl:variable name="isNextSiblingText" select="following-sibling::*[1]/text() = ''" />    
-  	<xsl:variable name="nextNodeCharClass" select="''" />
-  	<xsl:if test="following-sibling::*[1]/text() != ''">
-  		<xsl:variable name="nextNodeCharClass" select="'punctuNext'" />
-  	</xsl:if>
-  	<span class="w">
-  	<span class="text">
-    <xsl:choose>
-    	<xsl:when test="not(normalize-space($innerWordText))">&#160;</xsl:when>
-    	<xsl:otherwise><xsl:value-of select="$innerWordText" /></xsl:otherwise>	
-    </xsl:choose></span>
-    <xsl:if test="$StrongsNumbers = 'true' and (starts-with(@lemma, 'x-Strongs:') or starts-with(@lemma, 'strong:'))">
-      <xsl:call-template name="lemma">
-        <xsl:with-param name="lemma" select="@lemma"/>
-      </xsl:call-template>
-    </xsl:if>
-    <xsl:if test="$Morph = 'true' and (starts-with(@morph, 'x-Robinson:') or starts-with(@morph, 'robinson:'))">
-      <xsl:call-template name="morph">
-        <xsl:with-param name="morph" select="@morph"/>
-      </xsl:call-template>
-    </xsl:if>
-    <xsl:if test="$StrongsNumbers = 'true' and starts-with(@lemma, 'lemma.Strong:')">
-      <xsl:call-template name="lemma">
-        <xsl:with-param name="lemma" select="@lemma"/>
-      </xsl:call-template>
-    </xsl:if>
-    <xsl:if test="$Interlinear = 'true'">
-      <xsl:call-template name="interlinear">
-        <xsl:with-param name="lemma" select="@lemma" />
-        <xsl:with-param name="morph" select="@morph" />
-        <xsl:with-param name="osisID" select="../@osisID" />
-      </xsl:call-template>
-    </xsl:if>
-    
-    <!--
-        except when followed by a text node or non-printing node.
-        This is true whether the href is output or not.
-    -->
-    <xsl:variable name="siblings" select="../child::node()"/>
-    <xsl:variable name="next-position" select="position() + 1"/>
-    <xsl:if test="$siblings[$next-position] and name($siblings[$next-position]) != ''">
-      <xsl:text> </xsl:text>
-    </xsl:if>
-    </span>
-  </xsl:template>
-  
-  <xsl:template match="w" mode="jesus">
-    <!-- Output the content followed by all the lemmas and then all the morphs. -->
-    <xsl:apply-templates mode="jesus"/>
-    <xsl:if test="$StrongsNumbers = 'true' and (starts-with(@lemma, 'x-Strongs:') or starts-with(@lemma, 'strong:'))">
-      <xsl:call-template name="lemma">
-        <xsl:with-param name="lemma" select="@lemma"/>
-      </xsl:call-template>
-    </xsl:if>
-    <xsl:if test="$Morph = 'true' and (starts-with(@morph, 'x-Robinson:') or starts-with(@morph, 'robinson:'))">
-      <xsl:call-template name="morph">
-        <xsl:with-param name="morph" select="@morph"/>
-      </xsl:call-template>
-    </xsl:if>
-    <!--
-        except when followed by a text node or non-printing node.
-        This is true whether the href is output or not.
-    -->
-    <xsl:variable name="siblings" select="../child::node()"/>
-    <xsl:variable name="next-position" select="position() + 1"/>
-    <xsl:if test="$siblings[$next-position] and name($siblings[$next-position]) != ''">
-      <xsl:text> </xsl:text>
-    </xsl:if>
-  </xsl:template>
-  
-  <xsl:template name="lemma">
-    <xsl:param name="lemma"/>
-    <xsl:param name="part" select="0"/>
-    <xsl:param name="className" />
-    <xsl:param name="finalText" />
-    
-    <xsl:variable name="orig-lemma" select="substring-after($lemma, ':')"/>
-    <xsl:variable name="protocol">
-      <xsl:choose>
-        <xsl:when test="substring($orig-lemma, 1, 1) = 'H'">
-          <xsl:value-of select="$hebrew.def.protocol"/>
-        </xsl:when>
-        <xsl:when test="substring($orig-lemma, 1, 1) = 'G'">
-          <xsl:value-of select="$greek.def.protocol"/>
-        </xsl:when>
-        <xsl:otherwise>
-          <xsl:value-of select="$lex.def.protocol"/>
-        </xsl:otherwise>
-      </xsl:choose>
-    </xsl:variable>
-    <xsl:variable name="separator">
-      <xsl:choose>
-        <xsl:when test="contains($orig-lemma, '|') ">
-          <xsl:value-of select="'|'"/>
-        </xsl:when>
-        <xsl:when test="contains($orig-lemma, ' ')">
-          <xsl:value-of select="' '"/>
-        </xsl:when>
-      </xsl:choose>
-    </xsl:variable>
-    <xsl:variable name="sub">
-      <xsl:choose>
-        <xsl:when test="$separator != '' and $part = '0'">
-          <xsl:value-of select="$part + 1"/>
-        </xsl:when>
-        <xsl:otherwise>
-          <xsl:value-of select="$part"/>
-        </xsl:otherwise>
-      </xsl:choose>
-    </xsl:variable>
-    <xsl:choose>
-      <xsl:when test="$protocol = $lex.def.protocol">
-        <font class="lex">[<xsl:value-of select="$orig-lemma"/>]</font>
-      </xsl:when>
-      <xsl:when test="$separator = ''">
-        <span class="strongs {$className} {$orig-lemma}"><xsl:value-of select="concat($finalText, ' ', format-number(substring($orig-lemma, 2), '#'))" />
-        </span>
-      </xsl:when>
-      <xsl:otherwise>
-        <xsl:variable name="processedLemma" select="substring-before($orig-lemma, $separator)" />
-        <xsl:call-template name="lemma">
-          <xsl:with-param name="lemma" select="substring-after($lemma, $separator)"/>
-          <xsl:with-param name="className" select="concat($className, $processedLemma)" />
-          <xsl:with-param name="finalText" select="concat($finalText, ' ', format-number(substring($processedLemma,2),'#'))" />
-          <xsl:with-param name="part">
-            <xsl:choose>
-              <xsl:when test="$sub">
-                <xsl:value-of select="$sub + 1"/>
-              </xsl:when>
-              <xsl:otherwise>
-                <xsl:value-of select="1"/>
-              </xsl:otherwise>
-            </xsl:choose>
-          </xsl:with-param>
-        </xsl:call-template>
-      </xsl:otherwise>
-    </xsl:choose>
-  </xsl:template>
+	<xsl:template match="w">
+		<!-- Output the content followed by all the lemmas and then all the morphs. 
+			So, we know we have a number of lines to create, therefore, we'll create 
+			that many! -->
+		<xsl:variable name="innerWordText">
+			<xsl:apply-templates />
+		</xsl:variable>
+	
+		<!-- we check the next node too, since it might be punctuation, etc. In 
+			that case, it makes sense to include it in the bit word part that gets past 
+			down TODO TODO TODO -->
 
-  <xsl:template name="morph">
-    <xsl:param name="morph"/>
-    <xsl:param name="part" select="0"/>
-    <xsl:variable name="orig-work" select="substring-before($morph, ':')"/>
-    <xsl:variable name="orig-morph" select="substring-after($morph, ':')"/>
-    <xsl:variable name="protocol">
-      <xsl:choose>
-        <xsl:when test="starts-with($orig-work, 'x-Robinson') or starts-with($orig-work, 'robinson')">
-          <xsl:value-of select="$greek.morph.protocol"/>
-        </xsl:when>
-        <xsl:otherwise>
-          <xsl:value-of select="$hebrew.morph.protocol"/>
-        </xsl:otherwise>
-      </xsl:choose>
-    </xsl:variable>
-    <xsl:variable name="separator">
-      <xsl:choose>
-        <xsl:when test="contains($orig-morph, '|')">
-          <xsl:value-of select="'|'"/>
-        </xsl:when>
-        <xsl:when test="contains($orig-morph, ' ')">
-          <xsl:value-of select="' '"/>
-        </xsl:when>
-      </xsl:choose>
-    </xsl:variable>
-    <xsl:variable name="sub">
-      <xsl:choose>
-        <xsl:when test="$separator != '' and $part = '0'">
-          <xsl:value-of select="$part + 1"/>
-        </xsl:when>
-        <xsl:otherwise>
-          <xsl:value-of select="$part"/>
-        </xsl:otherwise>
-      </xsl:choose>
-    </xsl:variable>
-    <xsl:choose>
-      <xsl:when test="$separator = ''">
-        <!-- <sub class="morph"><a href="{$protocol}{$orig-morph}">M<xsl:number level="any" from="/osis//verse" format="1"/><xsl:number value="$sub" format="a"/></a></sub> -->
-        <sub class="morph"><a href="{$protocol}{$orig-morph}"><xsl:value-of select="$orig-morph"/></a></sub>
-      </xsl:when>
-      <xsl:otherwise>
-        <!-- <sub class="morph"><a href="{$protocol}{substring-before($orig-morph, $separator)}">M<xsl:number level="single" from="/osis//verse" format="1"/><xsl:number value="$sub" format="a"/></a>, </sub> -->
-        <sub class="morph"><a href="{$protocol}{substring-before($orig-morph, $separator)}"><xsl:value-of select="substring-before($orig-morph, $separator)"/></a>, </sub>
-        <xsl:call-template name="morph">
-          <xsl:with-param name="morph" select="substring-after($morph, $separator)"/>
-          <xsl:with-param name="part">
-            <xsl:choose>
-              <xsl:when test="$sub">
-                <xsl:value-of select="$sub + 1"/>
-              </xsl:when>
-              <xsl:otherwise>
-                <xsl:value-of select="1"/>
-              </xsl:otherwise>
-            </xsl:choose>
-          </xsl:with-param>
-        </xsl:call-template>
-      </xsl:otherwise>
-    </xsl:choose>
-  </xsl:template>
+		<!-- start the block -->
+		<span class="w">
+			<!-- 1st - Output first line or a blank if no text available. -->
+			<span class="text">
+				<xsl:call-template name="outputNonBlank">
+					<xsl:with-param name="string">
+						<xsl:value-of select="$innerWordText" />
+					</xsl:with-param>
+				</xsl:call-template>
+			</span>
 
+			<!-- 2nd - Output strongs if turned on. If turned on and no Strong then 
+				we need a blank. So always call template if turned on -->
+			<xsl:if test="$StrongsNumbers = 'true'">
+				<span class="strongs">
+					<xsl:value-of
+						select="jsword:com.tyndalehouse.step.core.utils.XslHelper.getSpanFromAttributeName(@lemma, $strongFunctionCall)" />
+				</span>
+			</xsl:if>
+
+			<!-- 3rd - Output morphology if turned on. If turned on and no morphology, 
+				we need a blank. -->
+			<xsl:if test="$Morph = 'true'">
+				<span class="morphs">
+					<xsl:value-of
+						select="jsword:com.tyndalehouse.step.core.utils.XslHelper.getSpanFromAttributeName(@morph, $morphFunctionCall)" />
+				</span>
+			</xsl:if>
+
+
+			<!-- 4th - We output the interlinears if provided and we do so recursively -->
+			<xsl:if test="normalize-space($interlinearVersion) != ''">
+				<xsl:call-template name="interlinear">
+					<xsl:with-param name="versions" select="$interlinearVersion" />
+				</xsl:call-template>
+			</xsl:if>
+			<!-- end the block -->
+		</span>
+	</xsl:template>
+  
   <xsl:template name="interlinear">
-    <xsl:param name="lemma" select="''"/>
-    <xsl:param name="morph" select="''"/>
-    <xsl:param name="osisID" />
-    <xsl:variable name="interlinearWord" select="jsword:getWord($interlinearProvider, $osisID, $lemma, $morph)"/>
-    <xsl:choose>
-    	<xsl:when test="normalize-space($interlinearWord) = ''" >&#160;</xsl:when>
-    	<xsl:otherwise><span class="interlinearText"><xsl:value-of select="$interlinearWord"/></span></xsl:otherwise>
-    </xsl:choose>
-  </xsl:template>
+  	<xsl:param name="versions" />  	
 
+	<xsl:variable name="nextVersion" select="normalize-space(substring-before($versions, ','))" />
 
+	<!--  if next version is not empty, then there was a comma, so we output this version and call template again -->
+	<xsl:choose>
+		<xsl:when test="normalize-space($nextVersion) != ''">
+			<span class="interlinear">
+				<xsl:call-template name="outputNonBlank">
+					<xsl:with-param name="string">
+						<xsl:value-of select="jsword:getWord($interlinearProvider, normalize-space($nextVersion), ../@osisID, @lemma, @morph)"></xsl:value-of>
+					</xsl:with-param>
+				</xsl:call-template>
+			</span>
+			<xsl:call-template name="interlinear">
+				<xsl:with-param name="versions" select="substring-after($versions, ',')" />
+			</xsl:call-template>
+		</xsl:when>
+		<!-- otherwise, then we can use the remainder as the version, as long as version not empty (for e.g. a trailing comma) -->
+		<xsl:otherwise>
+		    <xsl:if test="normalize-space($versions) != ''" >
+				<span class="interlinear">
+					<xsl:call-template name="outputNonBlank">
+						<xsl:with-param name="string">
+							<xsl:value-of select="jsword:getWord($interlinearProvider, normalize-space($versions), ../@osisID, @lemma, @morph)"></xsl:value-of>
+						</xsl:with-param>
+					</xsl:call-template>
+				</span>
+			</xsl:if>
+		</xsl:otherwise>
+	</xsl:choose>
+  </xsl:template>
+  
+  <xsl:template name="outputNonBlank">
+  	<xsl:param name="string" />
+  	<xsl:choose>
+  		<xsl:when test="normalize-space($string) != ''">
+  			<xsl:value-of select="$string" />
+  		</xsl:when>
+  		<xsl:otherwise><xsl:value-of select="'&#160;'" /></xsl:otherwise>
+  	</xsl:choose>
+  	
+  </xsl:template>
+  
   <!--=======================================================================-->
   <xsl:template match="seg">
     <xsl:choose>
@@ -1328,7 +1208,7 @@
   </xsl:template>
 
   <xsl:template match="transChange">
-    <span><em><xsl:apply-templates/></em></span>
+    <span class="w"><em><xsl:apply-templates/></em></span>
   </xsl:template>
   <xsl:template match="transChange" mode="jesus">
     <span class="w"><em><xsl:apply-templates/></em></span>

Added: trunk/step/step-core/src/main/resources/com/tyndalehouse/step/core/service/impl/old_interlinear.xsl
===================================================================
--- trunk/step/step-core/src/main/resources/com/tyndalehouse/step/core/service/impl/old_interlinear.xsl	                        (rev 0)
+++ trunk/step/step-core/src/main/resources/com/tyndalehouse/step/core/service/impl/old_interlinear.xsl	2010-11-21 21:46:24 UTC (rev 188)
@@ -0,0 +1,1555 @@
+<?xml version="1.0"?>
+<!--
+ * Distribution License:
+ * JSword is free software; you can redistribute it and/or modify it under
+ * the terms of the GNU Lesser General Public License, version 2.1 as published by
+ * the Free Software Foundation. This program 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 Lesser General Public License for more details.
+ *
+ * The License is available on the internet at:
+ *       http://www.gnu.org/copyleft/lgpl.html
+ * or by writing to:
+ *      Free Software Foundation, Inc.
+ *      59 Temple Place - Suite 330
+ *      Boston, MA 02111-1307, USA
+ *
+ * Copyright: 2005
+ *     The copyright to this program is held by it's authors.
+ *
+ * ID: $Id: default.xsl 1943 2009-03-25 11:43:28Z dmsmith $
+ -->
+ <!--
+ * Transforms OSIS to HTML for viewing within JSword browsers.
+ * Note: There are custom protocols which the browser must handle.
+ * 
+ * @see gnu.lgpl.License for license details.
+ *      The copyright to this program is held by it's authors.
+ * @author Joe Walker [joe at eireneh dot com]
+ * @author DM Smith [dmsmith555 at yahoo dot com]
+ * @author Chris Burrell [chris at burrell dot me dot uk] 
+ -->
+ <xsl:stylesheet
+  xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+  version="1.0"
+  xmlns:jsword="http://xml.apache.org/xalan/java"
+  extension-element-prefixes="jsword">
+
+  <!--  Version 3.0 is necessary to get br to work correctly. -->
+  <xsl:output method="html" version="3.0" omit-xml-declaration="yes" indent="no"/>
+
+  <!-- Be very careful about introducing whitespace into the document.
+       strip-space merely remove space between one tag and another tag.
+       This may cause significant whitespace to be removed.
+       
+       It is easy to have apply-templates on a line to itself which if
+       it encounters text before anything else will introduce whitespace.
+       With the browser we are using, span will introduce whitespace
+       but font does not. Therefore we use font as a span.
+    -->
+  <!-- gdef and hdef refer to hebrew and greek definitions keyed by strongs -->
+  <xsl:param name="greek.def.protocol" select="'gdef:'"/>
+  <xsl:param name="hebrew.def.protocol" select="'hdef:'"/>
+  <xsl:param name="lex.def.protocol" select="'lex:'"/>
+  <!-- currently these are not used, but they are for morphologic forms -->
+  <xsl:param name="greek.morph.protocol" select="'gmorph:'"/>
+  <xsl:param name="hebrew.morph.protocol" select="'hmorph:'"/>
+
+  <!-- The absolute base for relative references. -->
+  <xsl:param name="baseURL" select="''"/>
+
+  <!-- Whether to show Strongs or not -->
+  <xsl:param name="StrongsNumbers" select="'false'"/>
+
+  <!-- Whether to show morphologic forms or not -->
+  <xsl:param name="Morph" select="'false'"/>
+
+  <!-- Whether to start each verse on an new line or not -->
+  <xsl:param name="VLine" select="'false'"/>
+
+  <!-- Whether to show non-canonical "headings" or not -->
+  <xsl:param name="Headings" select="'true'"/>
+
+  <!-- Whether to show notes or not -->
+  <xsl:param name="Notes" select="'false'"/>
+
+  <!-- Whether to have linking cross references or not -->
+  <xsl:param name="XRef" select="'false'"/>
+
+  <!-- Whether to output no Verse numbers -->
+  <xsl:param name="NoVNum" select="'false'"/>
+
+  <!-- Whether to output Verse numbers or not -->
+  <xsl:param name="VNum" select="'true'"/>
+
+  <!-- Whether to output Chapter and Verse numbers or not -->
+  <xsl:param name="CVNum" select="'false'"/>
+
+  <!-- Whether to output Book, Chapter and Verse numbers or not -->
+  <xsl:param name="BCVNum" select="'false'"/>
+
+  <!-- Whether to output superscript verse numbers or normal size ones -->
+  <xsl:param name="TinyVNum" select="'true'"/>
+
+  <!-- The order of display. Hebrew is rtl (right to left) -->
+  <xsl:param name="direction" select="'ltr'"/>
+
+  <!-- Whether to show an interlinear and the provider helping with the lookup -->
+  <xsl:param name="Interlinear" select="'false'" />
+  <xsl:param name="interlinearVersion" select="''" />
+  <xsl:param name="interlinearReference" select="''" />
+
+  <!-- Create a global key factory from which OSIS ids will be generated -->
+  <xsl:variable name="keyf" select="jsword:org.crosswire.jsword.passage.PassageKeyFactory.instance()"/>
+  <!-- Create a global number shaper that can transform 0-9 into other number systems. -->
+  <xsl:variable name="shaper" select="jsword:org.crosswire.common.icu.NumberShaper.new()"/>
+  
+  <!--  set up interlinear provider, if we have requested it -->
+  <xsl:variable name="interlinearProvider" select="jsword:com.tyndalehouse.step.core.xsl.impl.InterlinearProviderImpl.new(string($interlinearVersion), string($interlinearReference))" />
+
+  <!--=======================================================================-->
+  <xsl:template match="/">
+      <div>
+        <!-- If there are notes, output a table with notes in the 2nd column. -->
+        <!-- There is a rendering bug which prevents the notes from adhering to the right edge. -->
+        <xsl:choose>
+          <xsl:when test="$Notes = 'true' and //note[not(@type = 'x-strongsMarkup')]">
+            <xsl:choose>
+              <xsl:when test="$direction != 'rtl'">
+                <table cols="2" cellpadding="5" cellspacing="5">
+                  <tr>
+                    <!-- The two rows are swapped until the bug is fixed. -->
+                    <td valign="top" class="notes">
+                      <p>&#160;</p>
+                      <xsl:apply-templates select="//verse" mode="print-notes"/>
+                    </td>
+                    <td valign="top" class="text">
+                      <xsl:apply-templates/>
+                    </td>
+                  </tr>
+                </table>
+              </xsl:when>
+              <xsl:otherwise>
+                <!-- reverse the table for Right to Left languages -->
+                <table cols="2" cellpadding="5" cellspacing="5">
+                  <!-- In a right to left, the alignment should be reversed too -->
+                  <tr align="right">
+                    <td valign="top" class="notes">
+                      <p>&#160;</p>
+                      <xsl:apply-templates select="//note" mode="print-notes"/>
+                    </td>
+                    <td valign="top" class="text">
+                      <xsl:apply-templates/>
+                    </td>
+                  </tr>
+                </table>
+              </xsl:otherwise>
+            </xsl:choose>
+          </xsl:when>
+          <xsl:otherwise>
+            <xsl:apply-templates/>
+          </xsl:otherwise>
+        </xsl:choose>
+      </div>
+  </xsl:template>
+
+  <!--=======================================================================-->
+  <!--
+    == A proper OSIS document has osis as its root.
+    == We dig deeper for its content.
+    -->
+  <xsl:template match="osis">
+    <xsl:apply-templates/>
+  </xsl:template>
+
+  <!--=======================================================================-->
+  <!--
+    == An OSIS document may contain more that one work.
+    == Each work is held in an osisCorpus element.
+    == If there is only one work, then this element will (should) be absent.
+    == Process each document in turn.
+    == It might be reasonable to dig into the header element of each work
+    == and get its title.
+    == Otherwise, we ignore the header and work elements and just process
+    == the osisText elements.
+    -->
+  <xsl:template match="osisCorpus">
+    <xsl:apply-templates select="osisText"/>
+  </xsl:template>
+
+  <!--=======================================================================-->
+  <!--
+    == Each work has an osisText element.
+    == We ignore the header and work elements and process its div elements.
+    == While divs can be milestoned, the osisText element requires container
+    == divs.
+    -->
+  <xsl:template match="osisText">
+    <xsl:apply-templates select="div"/>
+  </xsl:template>
+  
+  <!-- Ignore headers and its elements -->
+  <xsl:template match="header"/>
+  <xsl:template match="revisionDesc"/>
+  <xsl:template match="work"/>
+   <!-- <xsl:template match="title"/> who's parent is work -->
+  <xsl:template match="contributor"/>
+  <xsl:template match="creator"/>
+  <xsl:template match="subject"/>
+  <!-- <xsl:template match="date"/> who's parent is work -->
+  <xsl:template match="description"/>
+  <xsl:template match="publisher"/>
+  <xsl:template match="type"/>
+  <xsl:template match="format"/>
+  <xsl:template match="identifier"/>
+  <xsl:template match="source"/>
+  <xsl:template match="language"/>
+  <xsl:template match="relation"/>
+  <xsl:template match="coverage"/>
+  <xsl:template match="rights"/>
+  <xsl:template match="scope"/>
+  <xsl:template match="workPrefix"/>
+  <xsl:template match="castList"/>
+  <xsl:template match="castGroup"/>
+  <xsl:template match="castItem"/>
+  <xsl:template match="actor"/>
+  <xsl:template match="role"/>
+  <xsl:template match="roleDesc"/>
+  <xsl:template match="teiHeader"/>
+  <xsl:template match="refSystem"/>
+
+
+  <!-- Ignore titlePage -->
+  <xsl:template match="titlePage"/>
+
+  <!--=======================================================================-->
+  <!-- 
+    == Div provides the major containers for a work.
+    == Divs are milestoneable.
+    -->
+  <xsl:template match="div[@type='x-center']">
+    <div align="center">
+      <xsl:apply-templates/>
+    </div>
+  </xsl:template>
+
+  <xsl:template match="div">
+    <xsl:apply-templates/>
+  </xsl:template>
+
+  <xsl:template match="div" mode="jesus">
+    <xsl:apply-templates mode="jesus"/>
+  </xsl:template>
+
+  <!--=======================================================================-->
+  <!-- Handle verses as containers and as a start verse.                     -->
+  <xsl:template match="verse[not(@eID)]">
+    <!-- output each preverse element in turn -->
+    <xsl:for-each select=".//*[@subType = 'x-preverse' or @subtype = 'x-preverse']">
+      <xsl:choose>
+        <xsl:when test="local-name() = 'title'">
+          <!-- Always show canonical titles or if headings is turned on -->
+          <xsl:if test="@canonical = 'true' or $Headings = 'true'">
+            <h3 class="heading"><xsl:apply-templates /></h3>
+          </xsl:if>
+        </xsl:when>
+        <xsl:otherwise>
+          <xsl:apply-templates />
+        </xsl:otherwise>
+      </xsl:choose>
+    </xsl:for-each>
+    <!-- Handle the KJV paragraph marker. -->
+    <xsl:if test="milestone[@type = 'x-p']"><br/><br/></xsl:if>
+    <!-- If the verse doesn't start on its own line and -->
+    <!-- the verse is not the first verse of a set of siblings, -->
+    <!-- output an extra space. -->
+    <xsl:if test="$VLine = 'false' and preceding-sibling::*[local-name() = 'verse']">
+      <xsl:text>&#160;</xsl:text>
+    </xsl:if>
+    <!-- Always output the verse -->
+    <xsl:choose>
+      <xsl:when test="$VLine = 'true'">
+        <div class="l"><a name="{@osisID}"><xsl:call-template name="versenum"/></a><xsl:apply-templates/></div>
+      </xsl:when>
+      <xsl:otherwise>
+        <span class="interlinear"><xsl:call-template name="versenum"/><xsl:apply-templates/></span>
+        <!-- Follow the verse with an extra space -->
+        <!-- when they don't start on lines to themselves -->
+        <xsl:text> </xsl:text>
+      </xsl:otherwise>
+    </xsl:choose>
+  </xsl:template>
+
+  <xsl:template match="verse[not(@eID)]" mode="jesus">
+    <!-- If the verse doesn't start on its own line and -->
+    <!-- the verse is not the first verse of a set of siblings, -->
+    <!-- output an extra space. -->
+    <xsl:if test="$VLine = 'false' and preceding-sibling::*[local-name() = 'verse']">
+      <xsl:text>&#160;</xsl:text>
+    </xsl:if>
+    <xsl:variable name="title" select=".//title"/>
+    <xsl:if test="string-length($title) > 0">
+      <h3 class="heading"><xsl:value-of select="$title"/></h3>
+    </xsl:if>
+    <!-- Handle the KJV paragraph marker. -->
+    <xsl:if test="milestone[@type = 'x-p']"><br/><br/></xsl:if>
+    <!-- Always output the verse -->
+    <xsl:choose>
+      <xsl:when test="$VLine = 'true'">
+        <div class="l"><a name="{@osisID}"><xsl:call-template name="versenum"/></a><xsl:apply-templates mode="jesus"/></div>
+      </xsl:when>
+      <xsl:otherwise>
+        <xsl:call-template name="versenum"/><xsl:apply-templates mode="jesus"/>
+        <!-- Follow the verse with an extra space -->
+        <!-- when they don't start on lines to themselves -->
+        <xsl:text> </xsl:text>
+      </xsl:otherwise>
+    </xsl:choose>
+  </xsl:template>
+
+  <xsl:template match="verse" mode="print-notes">
+    <xsl:if test=".//note[not(@type) or not(@type = 'x-strongsMarkup')]">
+      <xsl:variable name="passage" select="jsword:getValidKey($keyf, @osisID)"/>
+      <a href="#{substring-before(concat(@osisID, ' '), ' ')}">
+        <xsl:value-of select="jsword:getName($passage)"/>
+      </a>
+      <xsl:apply-templates select=".//note" mode="print-notes" />
+      <div><xsl:text>&#160;</xsl:text></div>
+    </xsl:if>
+  </xsl:template>
+
+  <xsl:template name="versenum">
+    <!-- Are verse numbers wanted? -->
+    <xsl:if test="$NoVNum = 'false'">
+      <!-- An osisID can be a space separated list of them -->
+      <xsl:variable name="firstOsisID" select="substring-before(concat(@osisID, ' '), ' ')"/>
+      <xsl:variable name="book" select="substring-before($firstOsisID, '.')"/>
+      <xsl:variable name="chapter" select="jsword:shape($shaper, substring-before(substring-after($firstOsisID, '.'), '.'))"/>
+      <!-- If n is present use it for the number -->
+      <xsl:variable name="verse">
+        <xsl:choose>
+          <xsl:when test="@n">
+            <xsl:value-of select="jsword:shape($shaper, string(@n))"/>
+          </xsl:when>
+          <xsl:otherwise>
+            <xsl:value-of select="jsword:shape($shaper, substring-after(substring-after($firstOsisID, '.'), '.'))"/>
+          </xsl:otherwise>
+        </xsl:choose>
+      </xsl:variable>
+      <xsl:variable name="versenum">
+        <xsl:choose>
+          <xsl:when test="$BCVNum = 'true'">
+            <xsl:variable name="passage" select="jsword:getValidKey($keyf, @osisID)"/>
+            <xsl:value-of select="jsword:getName($passage)"/>
+          </xsl:when>
+          <xsl:when test="$CVNum = 'true'">
+            <xsl:value-of select="concat($chapter, ' : ', $verse)"/>
+          </xsl:when>
+          <xsl:otherwise>
+            <xsl:value-of select="$verse"/>
+          </xsl:otherwise>
+        </xsl:choose>
+      </xsl:variable>
+      <!--
+        == Surround versenum with dup
+        -->
+      <xsl:choose>
+        <xsl:when test="$TinyVNum = 'true' and $Notes = 'true'">
+          <span class="w"><a name="{@osisID}"><span class="verseNumber"><xsl:value-of select="$versenum"/></span></a></span>
+        </xsl:when>
+        <xsl:when test="$TinyVNum = 'true' and $Notes = 'false'">
+          <span class="w"><span class="verseNumber"><xsl:value-of select="$versenum"/></span></span>
+        </xsl:when>
+        <xsl:when test="$TinyVNum = 'false' and $Notes = 'true'">
+          <a name="{@osisID}">(<xsl:value-of select="$versenum"/>)</a>
+          <xsl:text> </xsl:text>
+        </xsl:when>
+        <xsl:otherwise>
+          (<xsl:value-of select="$versenum"/>)
+          <xsl:text> </xsl:text>
+        </xsl:otherwise>
+      </xsl:choose>
+    </xsl:if>
+    <xsl:if test="$VNum = 'false' and $Notes = 'true'">
+      <a name="{@osisID}"></a>
+    </xsl:if>
+  </xsl:template>
+
+  <!--=======================================================================-->
+  <xsl:template match="a">
+    <a href="{@href}"><xsl:apply-templates/></a>
+  </xsl:template>
+
+  <xsl:template match="a" mode="jesus">
+    <a href="{@href}"><xsl:apply-templates mode="jesus"/></a>
+  </xsl:template>
+
+  <!--=======================================================================-->
+  <!-- When we encounter a note, we merely output a link to the note. -->
+  <xsl:template match="note[@type = 'x-strongsMarkup']"/>
+  <xsl:template match="note[@type = 'x-strongsMarkup']" mode="jesus"/>
+  <xsl:template match="note[@type = 'x-strongsMarkup']" mode="print-notes"/>
+
+  <xsl:template match="note">
+    <xsl:if test="$Notes = 'true'">
+      <!-- If there is a following sibling that is a note, emit a separator -->
+      <xsl:variable name="siblings" select="../child::node()"/>
+      <xsl:variable name="next-position" select="position() + 1"/>
+      <xsl:choose>
+        <xsl:when test="name($siblings[$next-position]) = 'note'">
+          <sup class="note"><a href="#note-{generate-id(.)}"><xsl:call-template name="generateNoteXref"/></a>, </sup>
+        </xsl:when>
+        <xsl:otherwise>
+          <sup class="note"><a href="#note-{generate-id(.)}"><xsl:call-template name="generateNoteXref"/></a></sup>
+        </xsl:otherwise>
+      </xsl:choose>
+    </xsl:if>
+  </xsl:template>
+
+  <xsl:template match="note" mode="jesus">
+    <xsl:if test="$Notes = 'true'">
+     <!-- If there is a following sibling that is a note, emit a separator -->
+      <xsl:variable name="siblings" select="../child::node()"/>
+      <xsl:variable name="next-position" select="position() + 1"/>
+      <xsl:choose>
+        <xsl:when test="$siblings[$next-position] and name($siblings[$next-position]) = 'note'">
+          <sup class="note"><a href="#note-{generate-id(.)}"><xsl:call-template name="generateNoteXref"/></a>, </sup>
+        </xsl:when>
+        <xsl:otherwise>
+          <sup class="note"><a href="#note-{generate-id(.)}"><xsl:call-template name="generateNoteXref"/></a></sup>
+        </xsl:otherwise>
+      </xsl:choose>
+    </xsl:if>
+  </xsl:template>
+
+  <!--=======================================================================-->
+  <xsl:template match="note" mode="print-notes">
+    <div class="margin">
+      <strong><xsl:call-template name="generateNoteXref"/></strong>
+      <a name="note-{generate-id(.)}">
+        <xsl:text> </xsl:text>
+      </a>
+      <xsl:apply-templates/>
+    </div>
+  </xsl:template>
+
+  <!--
+    == If the n attribute is present then use that for the cross ref otherwise create a letter.
+    == Note: numbering restarts with each verse.
+    -->
+  <xsl:template name="generateNoteXref">
+    <xsl:choose>
+      <xsl:when test="@n">
+        <xsl:value-of select="@n"/>
+      </xsl:when>
+      <xsl:otherwise>
+        <xsl:number level="any" from="/osis//verse" format="a"/>
+      </xsl:otherwise>
+    </xsl:choose>
+  </xsl:template>
+
+  <!--=======================================================================-->
+  <xsl:template match="p">
+    <p><xsl:apply-templates/></p>
+  </xsl:template>
+  
+  <xsl:template match="p" mode="jesus">
+    <p><xsl:apply-templates mode="jesus"/></p>
+  </xsl:template>
+  
+  <!--=======================================================================-->
+  <xsl:template match="p" mode="print-notes">
+    <!-- FIXME: This ignores text in the note. -->
+    <!-- don't put para's in notes -->
+  </xsl:template>
+
+  <!--=======================================================================-->
+  <xsl:template match="w">
+    <!-- Output the content followed by all the lemmas and then all the morphs. -->
+    <xsl:variable name="innerWordText"><xsl:apply-templates/></xsl:variable>
+    <xsl:variable name="isNextSiblingText" select="following-sibling::*[1]/text() = ''" />    
+  	<xsl:variable name="nextNodeCharClass" select="''" />
+  	<xsl:if test="following-sibling::*[1]/text() != ''">
+  		<xsl:variable name="nextNodeCharClass" select="'punctuNext'" />
+  	</xsl:if>
+  	<span class="w">
+  	<span class="text">
+    <xsl:choose>
+    	<xsl:when test="not(normalize-space($innerWordText))">&#160;</xsl:when>
+    	<xsl:otherwise><xsl:value-of select="$innerWordText" /></xsl:otherwise>	
+    </xsl:choose></span>
+    <xsl:if test="$StrongsNumbers = 'true' and (starts-with(@lemma, 'x-Strongs:') or starts-with(@lemma, 'strong:'))">
+      <xsl:call-template name="lemma">
+        <xsl:with-param name="lemma" select="@lemma"/>
+      </xsl:call-template>
+    </xsl:if>
+    <xsl:if test="$Morph = 'true' and (starts-with(@morph, 'x-Robinson:') or starts-with(@morph, 'robinson:'))">
+      <xsl:call-template name="morph">
+        <xsl:with-param name="morph" select="@morph"/>
+      </xsl:call-template>
+    </xsl:if>
+    <xsl:if test="$StrongsNumbers = 'true' and starts-with(@lemma, 'lemma.Strong:')">
+      <xsl:call-template name="lemma">
+        <xsl:with-param name="lemma" select="@lemma"/>
+      </xsl:call-template>
+    </xsl:if>
+    <xsl:if test="$Interlinear = 'true'">
+      <xsl:call-template name="interlinear">
+        <xsl:with-param name="lemma" select="@lemma" />
+        <xsl:with-param name="morph" select="@morph" />
+        <xsl:with-param name="osisID" select="../@osisID" />
+      </xsl:call-template>
+    </xsl:if>
+    
+    <!--
+        except when followed by a text node or non-printing node.
+        This is true whether the href is output or not.
+    -->
+    <xsl:variable name="siblings" select="../child::node()"/>
+    <xsl:variable name="next-position" select="position() + 1"/>
+    <xsl:if test="$siblings[$next-position] and name($siblings[$next-position]) != ''">
+      <xsl:text> </xsl:text>
+    </xsl:if>
+    </span>
+  </xsl:template>
+  
+  <xsl:template match="w" mode="jesus">
+    <!-- Output the content followed by all the lemmas and then all the morphs. -->
+    <xsl:apply-templates mode="jesus"/>
+    <xsl:if test="$StrongsNumbers = 'true' and (starts-with(@lemma, 'x-Strongs:') or starts-with(@lemma, 'strong:'))">
+      <xsl:call-template name="lemma">
+        <xsl:with-param name="lemma" select="@lemma"/>
+      </xsl:call-template>
+    </xsl:if>
+    <xsl:if test="$Morph = 'true' and (starts-with(@morph, 'x-Robinson:') or starts-with(@morph, 'robinson:'))">
+      <xsl:call-template name="morph">
+        <xsl:with-param name="morph" select="@morph"/>
+      </xsl:call-template>
+    </xsl:if>
+    <!--
+        except when followed by a text node or non-printing node.
+        This is true whether the href is output or not.
+    -->
+    <xsl:variable name="siblings" select="../child::node()"/>
+    <xsl:variable name="next-position" select="position() + 1"/>
+    <xsl:if test="$siblings[$next-position] and name($siblings[$next-position]) != ''">
+      <xsl:text> </xsl:text>
+    </xsl:if>
+  </xsl:template>
+  
+  <xsl:template name="lemma">
+    <xsl:param name="lemma"/>
+    <xsl:param name="part" select="0"/>
+    <xsl:param name="className" />
+    <xsl:param name="finalText" />
+    
+    <xsl:variable name="orig-lemma" select="substring-after($lemma, ':')"/>
+    <xsl:variable name="protocol">
+      <xsl:choose>
+        <xsl:when test="substring($orig-lemma, 1, 1) = 'H'">
+          <xsl:value-of select="$hebrew.def.protocol"/>
+        </xsl:when>
+        <xsl:when test="substring($orig-lemma, 1, 1) = 'G'">
+          <xsl:value-of select="$greek.def.protocol"/>
+        </xsl:when>
+        <xsl:otherwise>
+          <xsl:value-of select="$lex.def.protocol"/>
+        </xsl:otherwise>
+      </xsl:choose>
+    </xsl:variable>
+    <xsl:variable name="separator">
+      <xsl:choose>
+        <xsl:when test="contains($orig-lemma, '|') ">
+          <xsl:value-of select="'|'"/>
+        </xsl:when>
+        <xsl:when test="contains($orig-lemma, ' ')">
+          <xsl:value-of select="' '"/>
+        </xsl:when>
+      </xsl:choose>
+    </xsl:variable>
+    <xsl:variable name="sub">
+      <xsl:choose>
+        <xsl:when test="$separator != '' and $part = '0'">
+          <xsl:value-of select="$part + 1"/>
+        </xsl:when>
+        <xsl:otherwise>
+          <xsl:value-of select="$part"/>
+        </xsl:otherwise>
+      </xsl:choose>
+    </xsl:variable>
+    <xsl:choose>
+    <!--  TODO, we change this and put a condition above to determine whether we chop off from 1, or 2 -->
+      <xsl:when test="$protocol = $lex.def.protocol">
+        <font class="lex">[<xsl:value-of select="$orig-lemma"/>]</font>
+      </xsl:when>
+      <xsl:when test="$separator = ''">
+        <span class="strongs {$className} {$orig-lemma}"><xsl:value-of select="concat($finalText, ' ', format-number(substring($orig-lemma, 2), '#'))" />
+        </span>
+      </xsl:when>
+      <xsl:otherwise>
+        <xsl:variable name="processedLemma" select="substring-before($orig-lemma, $separator)" />
+        <xsl:call-template name="lemma">
+          <xsl:with-param name="lemma" select="substring-after($lemma, $separator)"/>
+          <xsl:with-param name="className" select="concat($className, $processedLemma)" />
+          <xsl:with-param name="finalText" select="concat($finalText, ' ', format-number(substring($processedLemma,2),'#'))" />
+          <xsl:with-param name="part">
+            <xsl:choose>
+              <xsl:when test="$sub">
+                <xsl:value-of select="$sub + 1"/>
+              </xsl:when>
+              <xsl:otherwise>
+                <xsl:value-of select="1"/>
+              </xsl:otherwise>
+            </xsl:choose>
+          </xsl:with-param>
+        </xsl:call-template>
+      </xsl:otherwise>
+    </xsl:choose>
+  </xsl:template>
+
+  <xsl:template name="morph">
+    <xsl:param name="morph"/>
+    <xsl:param name="part" select="0"/>
+    <xsl:variable name="orig-work" select="substring-before($morph, ':')"/>
+    <xsl:variable name="orig-morph" select="substring-after($morph, ':')"/>
+    <xsl:variable name="protocol">
+      <xsl:choose>
+        <xsl:when test="starts-with($orig-work, 'x-Robinson') or starts-with($orig-work, 'robinson')">
+          <xsl:value-of select="$greek.morph.protocol"/>
+        </xsl:when>
+        <xsl:otherwise>
+          <xsl:value-of select="$hebrew.morph.protocol"/>
+        </xsl:otherwise>
+      </xsl:choose>
+    </xsl:variable>
+    <xsl:variable name="separator">
+      <xsl:choose>
+        <xsl:when test="contains($orig-morph, '|')">
+          <xsl:value-of select="'|'"/>
+        </xsl:when>
+        <xsl:when test="contains($orig-morph, ' ')">
+          <xsl:value-of select="' '"/>
+        </xsl:when>
+      </xsl:choose>
+    </xsl:variable>
+    <xsl:variable name="sub">
+      <xsl:choose>
+        <xsl:when test="$separator != '' and $part = '0'">
+          <xsl:value-of select="$part + 1"/>
+        </xsl:when>
+        <xsl:otherwise>
+          <xsl:value-of select="$part"/>
+        </xsl:otherwise>
+      </xsl:choose>
+    </xsl:variable>
+    <xsl:choose>
+      <xsl:when test="$separator = ''">
+        <!-- <sub class="morph"><a href="{$protocol}{$orig-morph}">M<xsl:number level="any" from="/osis//verse" format="1"/><xsl:number value="$sub" format="a"/></a></sub> -->
+        <sub class="morph"><a href="{$protocol}{$orig-morph}"><xsl:value-of select="$orig-morph"/></a></sub>
+      </xsl:when>
+      <xsl:otherwise>
+        <!-- <sub class="morph"><a href="{$protocol}{substring-before($orig-morph, $separator)}">M<xsl:number level="single" from="/osis//verse" format="1"/><xsl:number value="$sub" format="a"/></a>, </sub> -->
+        <sub class="morph"><a href="{$protocol}{substring-before($orig-morph, $separator)}"><xsl:value-of select="substring-before($orig-morph, $separator)"/></a>, </sub>
+        <xsl:call-template name="morph">
+          <xsl:with-param name="morph" select="substring-after($morph, $separator)"/>
+          <xsl:with-param name="part">
+            <xsl:choose>
+              <xsl:when test="$sub">
+                <xsl:value-of select="$sub + 1"/>
+              </xsl:when>
+              <xsl:otherwise>
+                <xsl:value-of select="1"/>
+              </xsl:otherwise>
+            </xsl:choose>
+          </xsl:with-param>
+        </xsl:call-template>
+      </xsl:otherwise>
+    </xsl:choose>
+  </xsl:template>
+
+  <xsl:template name="interlinear">
+    <xsl:param name="lemma" select="''"/>
+    <xsl:param name="morph" select="''"/>
+    <xsl:param name="osisID" />
+    <xsl:variable name="interlinearWord" select="jsword:getWord($interlinearProvider, $osisID, $lemma, $morph)"/>
+    <xsl:choose>
+    	<xsl:when test="normalize-space($interlinearWord) = ''" >&#160;</xsl:when>
+    	<xsl:otherwise><span class="interlinearText"><xsl:value-of select="$interlinearWord"/></span></xsl:otherwise>
+    </xsl:choose>
+  </xsl:template>
+
+
+  <!--=======================================================================-->
+  <xsl:template match="seg">
+    <xsl:choose>
+      <xsl:when test="starts-with(@type, 'color:')">
+        <font color="{substring-before(substring-after(@type, 'color: '), ';')}"><xsl:apply-templates/></font>
+      </xsl:when>
+      <xsl:when test="starts-with(@type, 'font-size:')">
+        <font size="{substring-before(substring-after(@type, 'font-size: '), ';')}"><xsl:apply-templates/></font>
+      </xsl:when>
+      <xsl:when test="@type = 'x-variant'">
+        <xsl:if test="@subType = 'x-class-1'">
+          <xsl:apply-templates/>
+        </xsl:if>
+      </xsl:when>
+      <xsl:otherwise>
+        <xsl:apply-templates/>
+      </xsl:otherwise>
+    </xsl:choose>
+  </xsl:template>
+  
+  <xsl:template match="seg" mode="jesus">
+    <xsl:choose>
+      <xsl:when test="starts-with(@type, 'color:')">
+        <font color="{substring-before(substring-after(@type, 'color: '), ';')}"><xsl:apply-templates mode="jesus"/></font>
+      </xsl:when>
+      <xsl:when test="starts-with(@type, 'font-size:')">
+        <font size="{substring-before(substring-after(@type, 'font-size: '), ';')}"><xsl:apply-templates mode="jesus"/></font>
+      </xsl:when>
+      <xsl:when test="@type = 'x-variant'">
+        <xsl:if test="@subType = 'x-class:1'">
+          <xsl:apply-templates mode="jesus"/>
+        </xsl:if>
+      </xsl:when>
+      <xsl:otherwise>
+        <xsl:apply-templates mode="jesus"/>
+      </xsl:otherwise>
+    </xsl:choose>
+  </xsl:template>
+  
+  <!--=======================================================================-->
+  <!-- expansion is OSIS, expan is TEI -->
+  <xsl:template match="abbr">
+    <font class="abbr">
+      <xsl:if test="@expansion">
+        <xsl:attribute name="title">
+          <xsl:value-of select="@expansion"/>
+        </xsl:attribute>
+      </xsl:if>
+      <xsl:if test="@expan">
+        <xsl:attribute name="title">
+          <xsl:value-of select="@expan"/>
+        </xsl:attribute>
+      </xsl:if>
+      <xsl:apply-templates/>
+    </font>
+  </xsl:template>
+
+  <xsl:template match="abbr" mode="jesus">
+    <font class="abbr">
+      <xsl:if test="@expansion">
+        <xsl:attribute name="title">
+          <xsl:value-of select="@expansion"/>
+        </xsl:attribute>
+      </xsl:if>
+      <xsl:if test="@expan">
+        <xsl:attribute name="title">
+          <xsl:value-of select="@expan"/>
+        </xsl:attribute>
+      </xsl:if>
+      <xsl:apply-templates mode="jesus"/>
+    </font>
+  </xsl:template>
+
+  <!--=======================================================================-->
+  <xsl:template match="speaker[@who = 'Jesus']">
+    <font class="jesus"><xsl:apply-templates mode="jesus"/></font>
+  </xsl:template>
+
+  <xsl:template match="speaker">
+    <font class="speech"><xsl:apply-templates/></font>
+  </xsl:template>
+
+  <!--=======================================================================-->
+  <xsl:template match="title[@subType ='x-preverse' or @subtype = 'x-preverse']">
+  <!-- Done by a line in [verse]
+    <h3 class="heading">
+      <xsl:apply-templates/>
+    </h3>
+  -->
+  </xsl:template>
+
+  <xsl:template match="title[@subType ='x-preverse' or @subtype = 'x-preverse']" mode="jesus">
+  <!-- Done by a line in [verse]
+    <h3 class="heading">
+      <xsl:apply-templates/>
+    </h3>
+  -->
+  </xsl:template>
+
+  <!--=======================================================================-->
+  <xsl:template match="title[@level]">
+    <!-- Always show canonical titles or if headings is turned on -->
+    <xsl:if test="@canonical = 'true' or $Headings = 'true'">
+      <xsl:choose>
+        <xsl:when test="@level = '1'">
+          <h1 class="level"><xsl:apply-templates/></h1>
+        </xsl:when>
+        <xsl:when test="@level = '2'">
+          <h2 class="level"><xsl:apply-templates/></h2>
+        </xsl:when>
+        <xsl:when test="@level = '3'">
+          <h3 class="level"><xsl:apply-templates/></h3>
+        </xsl:when>
+        <xsl:when test="@level = '4'">
+          <h4 class="level"><xsl:apply-templates/></h4>
+        </xsl:when>
+        <xsl:when test="@level = '5'">
+          <h5 class="level"><xsl:apply-templates/></h5>
+        </xsl:when>
+        <xsl:otherwise>
+          <h6 class="level"><xsl:apply-templates/></h6>
+        </xsl:otherwise>
+      </xsl:choose>
+    </xsl:if>
+  </xsl:template>
+
+  <xsl:template match="title[@level]" mode="jesus">
+    <!-- Always show canonical titles or if headings is turned on -->
+    <xsl:if test="@canonical = 'true' or $Headings = 'true'">
+      <xsl:choose>
+        <xsl:when test="@level = '1'">
+          <h1 class="level"><xsl:apply-templates/></h1>
+        </xsl:when>
+        <xsl:when test="@level = '2'">
+          <h2 class="level"><xsl:apply-templates/></h2>
+        </xsl:when>
+        <xsl:when test="@level = '3'">
+          <h3 class="level"><xsl:apply-templates/></h3>
+        </xsl:when>
+        <xsl:when test="@level = '4'">
+          <h4 class="level"><xsl:apply-templates/></h4>
+        </xsl:when>
+        <xsl:when test="@level = '5'">
+          <h5 class="level"><xsl:apply-templates/></h5>
+        </xsl:when>
+        <xsl:otherwise>
+          <h6 class="level"><xsl:apply-templates/></h6>
+        </xsl:otherwise>
+      </xsl:choose>
+    </xsl:if>
+  </xsl:template>
+
+  <!--=======================================================================-->
+  <xsl:template match="title">
+    <!-- Always show canonical titles or if headings is turned on -->
+    <xsl:if test="@canonical = 'true' or $Headings = 'true'">
+      <h2 class="heading"><xsl:apply-templates/></h2>
+    </xsl:if>
+  </xsl:template>
+
+  <xsl:template match="title" mode="jesus">
+    <!-- Always show canonical titles or if headings is turned on -->
+    <xsl:if test="@canonical = 'true' or $Headings = 'true'">
+      <h2 class="heading"><xsl:apply-templates/></h2>
+    </xsl:if>
+  </xsl:template>
+
+  <!--=======================================================================-->
+  <xsl:template match="reference">
+    <xsl:choose>
+      <xsl:when test="$XRef = 'true'">
+        <a href="bible://{@osisRef}"><xsl:apply-templates/></a>
+      </xsl:when>
+      <xsl:otherwise>
+        <xsl:apply-templates/>
+      </xsl:otherwise>
+    </xsl:choose>
+  </xsl:template>
+  
+  <xsl:template match="reference" mode="jesus">
+    <xsl:choose>
+      <xsl:when test="$XRef = 'true'">
+        <a href="bible://{@osisRef}"><xsl:apply-templates mode="jesus"/></a>
+      </xsl:when>
+      <xsl:otherwise>
+        <xsl:apply-templates mode="jesus"/>
+      </xsl:otherwise>
+    </xsl:choose>
+  </xsl:template>
+  
+  <!--=======================================================================-->
+  <xsl:template match="caption">
+    <div class="caption"><xsl:apply-templates/></div>
+  </xsl:template>
+  
+  <xsl:template match="caption" mode="jesus">
+    <div class="caption"><xsl:apply-templates/></div>
+  </xsl:template>
+  
+  <xsl:template match="catchWord">
+    <xsl:apply-templates/>
+  </xsl:template>
+  
+  <xsl:template match="catchWord" mode="jesus">
+    <xsl:apply-templates mode="jesus"/>
+  </xsl:template>
+  
+  <!--
+      <cell> is handled shortly after <table> below and thus does not appear
+      here.
+  -->
+  
+  <xsl:template match="closer">
+    <xsl:apply-templates/>
+  </xsl:template>
+  
+  <xsl:template match="closer" mode="jesus">
+    <xsl:apply-templates mode="jesus"/>
+  </xsl:template>
+  
+  <xsl:template match="date">
+    <xsl:apply-templates/>
+  </xsl:template>
+  
+  <xsl:template match="date" mode="jesus">
+    <xsl:apply-templates mode="jesus"/>
+  </xsl:template>
+  
+  <xsl:template match="divineName">
+    <xsl:apply-templates mode="small-caps"/>
+  </xsl:template>
+  
+  <xsl:template match="divineName" mode="jesus">
+    <xsl:apply-templates mode="small-caps"/>
+  </xsl:template>
+  
+  <xsl:template match="figure">
+    <div class="figure">
+      <xsl:choose>
+        <xsl:when test="starts-with(@src, '/')">
+          <img src="{concat($baseURL, @src)}"/>   <!-- FIXME: Not necessarily an image... -->
+        </xsl:when>
+        <xsl:otherwise>
+          <img src="{concat($baseURL, '/',  @src)}"/>   <!-- FIXME: Not necessarily an image... -->
+        </xsl:otherwise>
+      </xsl:choose>
+      <xsl:apply-templates/>
+    </div>
+  </xsl:template>
+  
+  <xsl:template match="figure" mode="jesus">
+    <div class="figure">
+      <xsl:choose>
+        <xsl:when test="starts-with(@src, '/')">
+          <img src="{concat($baseURL, @src)}"/>   <!-- FIXME: Not necessarily an image... -->
+        </xsl:when>
+        <xsl:otherwise>
+          <img src="{concat($baseURL, '/',  @src)}"/>   <!-- FIXME: Not necessarily an image... -->
+        </xsl:otherwise>
+      </xsl:choose>
+      <xsl:apply-templates mode="jesus"/>
+    </div>
+  </xsl:template>
+  
+  <xsl:template match="foreign">
+    <em class="foreign"><xsl:apply-templates/></em>
+  </xsl:template>
+  
+  <xsl:template match="foreign" mode="jesus">
+    <em class="foreign"><xsl:apply-templates mode="jesus"/></em>
+  </xsl:template>
+  
+  <!-- This is a subheading. -->
+  <xsl:template match="head//head">
+    <h5 class="head"><xsl:apply-templates/></h5>
+  </xsl:template>
+  
+  <!-- This is a top-level heading. -->
+  <xsl:template match="head">
+    <h4 class="head"><xsl:apply-templates/></h4>
+  </xsl:template>
+  
+  <xsl:template match="index">
+    <a name="index{@id}" class="index"/>
+  </xsl:template>
+
+  <xsl:template match="inscription">
+    <xsl:apply-templates mode="small-caps"/>
+  </xsl:template>
+
+  <xsl:template match="inscription" mode="jesus">
+    <xsl:apply-templates mode="small-caps"/>
+  </xsl:template>
+
+  <xsl:template match="item">
+    <li class="item"><xsl:apply-templates/></li>
+  </xsl:template>
+
+  <xsl:template match="item" mode="jesus">
+    <li class="item"><xsl:apply-templates mode="jesus"/></li>
+  </xsl:template>
+  
+  <!--
+      <item> and <label> are covered by <list> below and so do not appear here.
+  -->
+
+  <xsl:template match="lg">
+    <div class="lg"><xsl:apply-templates/></div>
+  </xsl:template>
+  
+  <xsl:template match="lg" mode="jesus">
+    <div class="lg"><xsl:apply-templates mode="jesus"/></div>
+  </xsl:template>
+  
+  <xsl:template match="lg[@sID or @eID]"/>
+  <xsl:template match="lg[@sID or @eID]" mode="jesus"/>
+
+  <xsl:template match="l[@sID]"/>
+  <xsl:template match="l[@sID]" mode="jesus"/>
+
+  <xsl:template match="l[@eID]"><br/></xsl:template>
+  <xsl:template match="l[@eID]" mode="jesus"><br/></xsl:template>
+
+  <xsl:template match="l">
+    <xsl:apply-templates/><br/>
+  </xsl:template>
+  
+  <xsl:template match="l" mode="jesus">
+    <xsl:apply-templates mode="jesus"/><br/>
+  </xsl:template>
+
+  <!-- While a BR is a break, if it is immediately followed by punctuation,
+       indenting this rule can introduce whitespace.
+    -->
+  <xsl:template match="lb"><br/></xsl:template>
+  <xsl:template match="lb" mode="jesus"><br/></xsl:template>
+
+  <xsl:template match="list">
+    <xsl:choose>
+      <xsl:when test="label">
+        <!-- If there are <label>s in the list, it's a <dl>. -->
+        <dl class="list">
+          <xsl:for-each select="node()">
+            <xsl:choose>
+              <xsl:when test="self::label">
+                <dt class="label"><xsl:apply-templates/></dt>
+              </xsl:when>
+              <xsl:when test="self::item">
+                <dd class="item"><xsl:apply-templates/></dd>
+              </xsl:when>
+              <xsl:when test="self::list">
+                <dd class="list-wrapper"><xsl:apply-templates select="."/></dd>
+              </xsl:when>
+              <xsl:otherwise>
+                <xsl:apply-templates/>
+              </xsl:otherwise>
+            </xsl:choose>
+          </xsl:for-each>
+        </dl>
+      </xsl:when>
+
+      <xsl:otherwise>
+        <!-- If there are no <label>s in the list, it's a plain old <ul>. -->
+        <ul class="list">
+          <xsl:for-each select="node()">
+            <xsl:choose>
+              <xsl:when test="self::item">
+                <li class="item"><xsl:apply-templates/></li>
+              </xsl:when>
+              <xsl:when test="self::list">
+                <li class="list-wrapper"><xsl:apply-templates select="."/></li>
+              </xsl:when>
+              <xsl:otherwise>
+                <xsl:apply-templates/>
+              </xsl:otherwise>
+            </xsl:choose>
+          </xsl:for-each>
+        </ul>
+      </xsl:otherwise>
+    </xsl:choose>
+  </xsl:template>
+
+
+  <xsl:template match="list" mode="jesus">
+    <xsl:choose>
+      <xsl:when test="label">
+        <!-- If there are <label>s in the list, it's a <dl>. -->
+        <dl class="list">
+          <xsl:for-each select="node()">
+            <xsl:choose>
+              <xsl:when test="self::label">
+                <dt class="label"><xsl:apply-templates mode="jesus"/></dt>
+              </xsl:when>
+              <xsl:when test="self::item">
+                <dd class="item"><xsl:apply-templates mode="jesus"/></dd>
+              </xsl:when>
+              <xsl:when test="self::list">
+                <dd class="list-wrapper"><xsl:apply-templates select="." mode="jesus"/></dd>
+              </xsl:when>
+              <xsl:otherwise>
+                <xsl:apply-templates mode="jesus"/>
+              </xsl:otherwise>
+            </xsl:choose>
+          </xsl:for-each>
+        </dl>
+      </xsl:when>
+
+      <xsl:otherwise>
+        <!-- If there are no <label>s in the list, it's a plain old <ul>. -->
+        <ul class="list">
+          <xsl:for-each select="node()">
+            <xsl:choose>
+              <xsl:when test="self::item">
+                <li class="item"><xsl:apply-templates mode="jesus"/></li>
+              </xsl:when>
+              <xsl:when test="self::list">
+                <li class="list-wrapper"><xsl:apply-templates select="." mode="jesus"/></li>
+              </xsl:when>
+              <xsl:otherwise>
+                <xsl:apply-templates mode="jesus"/>
+              </xsl:otherwise>
+            </xsl:choose>
+          </xsl:for-each>
+        </ul>
+      </xsl:otherwise>
+    </xsl:choose>
+  </xsl:template>
+
+  <xsl:template match="mentioned">
+    <xsl:apply-templates/>
+  </xsl:template>
+  
+  <xsl:template match="mentioned" mode="jesus">
+    <xsl:apply-templates mode="jesus"/>
+  </xsl:template>
+  
+  <!-- Milestones represent characteristics of the original manuscript.
+    == that are being preserved. For this reason, most are ignored.
+    ==
+    == The defined types are:
+    == column   Marks the end of a column where there is a multi-column display.
+    == footer   Marks the footer region of a page.
+    == halfLine Used to mark half-line units if not otherwise encoded.
+    == header   Marks the header region of a page.
+    == line     Marks line breaks, particularly important in recording appearance of an original text, such as a manuscript.
+    == pb       Marks a page break in a text.
+    == screen   Marks a preferred place for breaks in an on-screen rendering of the text.
+    == cQuote   Marks the location of a continuation quote mark, with marker containing the publishers mark.
+    -->
+  <!--  This is used by the KJV for paragraph markers. -->
+  <xsl:template match="milestone[@type = 'x-p']"><xsl:text> </xsl:text><xsl:value-of select="@marker"/><xsl:text> </xsl:text></xsl:template>
+  <xsl:template match="milestone[@type = 'x-p']" mode="jesus"><xsl:text> </xsl:text><xsl:value-of select="@marker"/><xsl:text> </xsl:text></xsl:template>
+
+  <xsl:template match="milestone[@type = 'cQuote']">
+    <xsl:value-of select="@marker"/>
+  </xsl:template>
+
+  <xsl:template match="milestone[@type = 'cQuote']" mode="jesus">
+    <xsl:value-of select="@marker"/>
+  </xsl:template>
+
+  <xsl:template match="milestone[@type = 'line']"><br/></xsl:template>
+
+  <xsl:template match="milestone[@type = 'line']" mode="jesus"><br/></xsl:template>
+
+  <!--
+    == Milestone start and end are deprecated.
+    == At this point we expect them to not be in the document.
+    == These have been replace with milestoneable elements.
+    -->
+  <xsl:template match="milestoneStart"/>
+  <xsl:template match="milestoneEnd"/>
+  
+  <xsl:template match="name">
+    <xsl:apply-templates/>
+  </xsl:template>
+
+  <xsl:template match="name" mode="jesus">
+    <xsl:apply-templates mode="jesus"/>
+  </xsl:template>
+
+  <!-- If there is a milestoned q then just output a quotation mark -->
+  <xsl:template match="q[@sID or @eID]">
+    <xsl:choose>
+      <xsl:when test="@marker"><xsl:value-of select="@marker"/></xsl:when>
+      <!-- The chosen mark should be based on the work's author's locale. -->
+      <xsl:otherwise>"</xsl:otherwise>
+    </xsl:choose>
+  </xsl:template>
+  
+  <xsl:template match="q[@sID or @eID]" mode="jesus">
+    <xsl:choose>
+      <xsl:when test="@marker"><xsl:value-of select="@marker"/></xsl:when>
+      <!-- The chosen mark should be based on the work's author's locale. -->
+      <xsl:otherwise>"</xsl:otherwise>
+    </xsl:choose>
+  </xsl:template>
+  
+  <xsl:template match="q[@who = 'Jesus']">
+    <font class="jesus"><xsl:value-of select="@marker"/><xsl:apply-templates mode="jesus"/><xsl:value-of select="@marker"/></font>
+  </xsl:template>
+
+  <xsl:template match="q[@type = 'blockquote']">
+    <blockquote class="q"><xsl:value-of select="@marker"/><xsl:apply-templates/><xsl:value-of select="@marker"/></blockquote>
+  </xsl:template>
+
+  <xsl:template match="q[@type = 'blockquote']" mode="jesus">
+    <blockquote class="q"><xsl:value-of select="@marker"/><xsl:apply-templates mode="jesus"/><xsl:value-of select="@marker"/></blockquote>
+  </xsl:template>
+
+  <xsl:template match="q[@type = 'citation']">
+    <blockquote class="q"><xsl:value-of select="@marker"/><xsl:apply-templates/><xsl:value-of select="@marker"/></blockquote>
+  </xsl:template>
+
+  <xsl:template match="q[@type = 'citation']" mode="jesus">
+    <blockquote class="q"><xsl:value-of select="@marker"/><xsl:apply-templates mode="jesus"/><xsl:value-of select="@marker"/></blockquote>
+  </xsl:template>
+
+  <xsl:template match="q[@type = 'embedded']">
+    <xsl:choose>
+      <xsl:when test="@marker">
+        <xsl:value-of select="@marker"/><xsl:apply-templates/><xsl:value-of select="@marker"/>
+      </xsl:when>
+      <xsl:otherwise>
+        <quote class="q"><xsl:apply-templates/></quote>
+      </xsl:otherwise>
+    </xsl:choose>
+  </xsl:template>
+  
+  <xsl:template match="q[@type = 'embedded']" mode="jesus">
+    <xsl:choose>
+      <xsl:when test="@marker">
+      <xsl:value-of select="@marker"/><xsl:apply-templates mode="jesus"/><xsl:value-of select="@marker"/>
+      </xsl:when>
+      <xsl:otherwise>
+        <quote class="q"><xsl:apply-templates/></quote>
+      </xsl:otherwise>
+    </xsl:choose>
+  </xsl:template>
+  
+  <!-- An alternate reading. -->
+  <xsl:template match="rdg">
+    <xsl:apply-templates/>
+  </xsl:template>
+
+   <xsl:template match="rdg" mode="jesus">
+    <xsl:apply-templates mode="jesus"/>
+  </xsl:template>
+
+  <!--
+      <row> is handled near <table> below and so does not appear here.
+  -->
+  
+  <xsl:template match="salute">
+    <xsl:apply-templates/>
+  </xsl:template>
+  
+ <!-- Avoid adding whitespace -->
+  <xsl:template match="salute" mode="jesus">
+    <xsl:apply-templates mode="jesus"/>
+  </xsl:template>
+
+  <xsl:template match="signed">
+    <xsl:apply-templates/>
+  </xsl:template>
+
+  <xsl:template match="signed" mode="jesus">
+    <xsl:apply-templates mode="jesus"/>
+  </xsl:template>
+
+  <xsl:template match="speech">
+    <div class="speech"><xsl:apply-templates/></div>
+  </xsl:template>
+  
+  <xsl:template match="speech" mode="jesus">
+    <div class="speech"><xsl:apply-templates mode="jesus"/></div>
+  </xsl:template>
+
+  <xsl:template match="table">
+    <table class="table">
+      <xsl:copy-of select="@rows|@cols"/>
+      <xsl:if test="head">
+        <thead class="head"><xsl:apply-templates select="head"/></thead>
+      </xsl:if>
+      <tbody><xsl:apply-templates select="row"/></tbody>
+    </table>
+  </xsl:template>
+
+  <xsl:template match="row">
+    <tr class="row"><xsl:apply-templates/></tr>
+  </xsl:template>
+  
+  <xsl:template match="cell">
+    <xsl:variable name="element-name">
+      <xsl:choose>
+        <xsl:when test="@role = 'label'">
+          <xsl:text>th</xsl:text>
+        </xsl:when>
+        <xsl:otherwise>
+          <xsl:text>td</xsl:text>
+        </xsl:otherwise>
+      </xsl:choose>
+    </xsl:variable>
+    <xsl:variable name="cell-direction">
+      <xsl:if test="@xml:lang">
+        <xsl:call-template name="getDirection">
+         <xsl:with-param name="lang"><xsl:value-of select="@xml:lang"/></xsl:with-param>
+        </xsl:call-template>
+      </xsl:if>
+    </xsl:variable>
+    <xsl:element name="{$element-name}">
+      <xsl:attribute name="class">cell</xsl:attribute>
+      <xsl:attribute name="valign">top</xsl:attribute>
+      <xsl:if test="@xml:lang">
+        <xsl:attribute name="dir">
+          <xsl:value-of select="$cell-direction"/>
+        </xsl:attribute>
+      </xsl:if>
+      <xsl:if test="$cell-direction = 'rtl'">
+        <xsl:attribute name="align">
+          <xsl:value-of select="'right'"/>
+        </xsl:attribute>
+      </xsl:if>
+      <xsl:if test="@rows">
+        <xsl:attribute name="rowspan">
+          <xsl:value-of select="@rows"/>
+        </xsl:attribute>
+      </xsl:if>
+      <xsl:if test="@cols">
+        <xsl:attribute name="colspan">
+          <xsl:value-of select="@cols"/>
+        </xsl:attribute>
+      </xsl:if>
+      <!-- hack alert -->
+      <xsl:choose>
+        <xsl:when test="$cell-direction = 'rtl'">
+          <xsl:text>&#8235;</xsl:text><xsl:apply-templates/><xsl:text>&#8236;</xsl:text>
+        </xsl:when>
+        <xsl:when test="$cell-direction = 'ltr'">
+          <xsl:text>&#8234;</xsl:text><xsl:apply-templates/><xsl:text>&#8236;</xsl:text>
+        </xsl:when>
+        <xsl:otherwise>
+          <xsl:apply-templates/>
+        </xsl:otherwise>
+      </xsl:choose>
+    </xsl:element>
+  </xsl:template>
+
+  <xsl:template match="transChange">
+    <span><em><xsl:apply-templates/></em></span>
+  </xsl:template>
+  <xsl:template match="transChange" mode="jesus">
+    <span class="w"><em><xsl:apply-templates/></em></span>
+  </xsl:template>
+  
+  <!-- @type is OSIS, @rend is TEI -->
+  <xsl:template match="hi">
+    <xsl:variable name="style">
+      <xsl:choose>
+        <xsl:when test="@type">
+          <xsl:value-of select="@type"/>
+        </xsl:when>
+        <xsl:otherwise>
+          <xsl:value-of select="@rend"/>
+        </xsl:otherwise>
+      </xsl:choose>
+    </xsl:variable>
+    <xsl:choose>
+      <xsl:when test="$style = 'acrostic'">
+        <xsl:apply-templates/>
+      </xsl:when>
+      <xsl:when test="$style = 'bold'">
+        <strong><xsl:apply-templates/></strong>
+      </xsl:when>
+      <xsl:when test="$style = 'emphasis'">
+        <em><xsl:apply-templates/></em>
+      </xsl:when>
+      <xsl:when test="$style = 'illuminated'">
+        <strong><em><xsl:apply-templates/></em></strong>
+      </xsl:when>
+      <xsl:when test="$style = 'italic'">
+        <em><xsl:apply-templates/></em>
+      </xsl:when>
+      <xsl:when test="$style = 'line-through'">
+        <font class="strike"><xsl:apply-templates/></font>
+      </xsl:when>
+      <xsl:when test="$style = 'normal'">
+        <font class="normal"><xsl:apply-templates/></font>
+      </xsl:when>
+      <xsl:when test="$style = 'small-caps'">
+        <font class="small-caps"><xsl:apply-templates/></font>
+      </xsl:when>
+      <xsl:when test="$style = 'sub'">
+        <sub><xsl:apply-templates/></sub>
+      </xsl:when>
+      <xsl:when test="$style = 'super'">
+        <sup><xsl:apply-templates/></sup>
+      </xsl:when>
+      <xsl:when test="$style = 'underline'">
+        <u><xsl:apply-templates/></u>
+      </xsl:when>
+      <xsl:when test="$style = 'x-caps'">
+        <font class="caps"><xsl:apply-templates/></font>
+      </xsl:when>
+      <xsl:otherwise>
+        <xsl:apply-templates/>
+      </xsl:otherwise>
+    </xsl:choose>
+  </xsl:template>
+
+  <xsl:template match="hi" mode="jesus">
+    <xsl:variable name="style">
+      <xsl:choose>
+        <xsl:when test="@type">
+          <xsl:value-of select="@type"/>
+        </xsl:when>
+        <xsl:otherwise>
+          <xsl:value-of select="@rend"/>
+        </xsl:otherwise>
+      </xsl:choose>
+    </xsl:variable>
+    <xsl:choose>
+      <xsl:when test="$style = 'acrostic'">
+        <xsl:apply-templates/>
+      </xsl:when>
+      <xsl:when test="$style = 'bold'">
+        <strong><xsl:apply-templates/></strong>
+      </xsl:when>
+      <xsl:when test="$style = 'emphasis'">
+        <em><xsl:apply-templates/></em>
+      </xsl:when>
+      <xsl:when test="$style = 'illuminated'">
+        <strong><em><xsl:apply-templates/></em></strong>
+      </xsl:when>
+      <xsl:when test="$style = 'italic'">
+        <em><xsl:apply-templates/></em>
+      </xsl:when>
+      <xsl:when test="$style = 'line-through'">
+        <font class="strike"><xsl:apply-templates/></font>
+      </xsl:when>
+      <xsl:when test="$style = 'normal'">
+        <font class="normal"><xsl:apply-templates/></font>
+      </xsl:when>
+      <xsl:when test="$style = 'small-caps'">
+        <font class="small-caps"><xsl:apply-templates/></font>
+      </xsl:when>
+      <xsl:when test="$style = 'sub'">
+        <sub><xsl:apply-templates/></sub>
+      </xsl:when>
+      <xsl:when test="$style = 'super'">
+        <sup><xsl:apply-templates/></sup>
+      </xsl:when>
+      <xsl:when test="$style = 'underline'">
+        <u><xsl:apply-templates/></u>
+      </xsl:when>
+      <xsl:when test="$style = 'x-caps'">
+        <font class="caps"><xsl:apply-templates/></font>
+      </xsl:when>
+      <xsl:otherwise>
+        <xsl:apply-templates/>
+      </xsl:otherwise>
+    </xsl:choose>
+  </xsl:template>
+
+  <!--
+    The following elements are actually TEI and there is some expectation
+    that these will make it into OSIS.
+  -->
+  <xsl:template match="superentry">
+    <!-- output each preverse element in turn -->
+    <xsl:for-each select="entry|entryFree">
+      <xsl:apply-templates/><br/><br/>
+    </xsl:for-each>
+  </xsl:template>
+
+  <xsl:template match="entry">
+    <xsl:apply-templates/>
+  </xsl:template>
+
+  <xsl:template match="entryFree">
+    <xsl:apply-templates/>
+  </xsl:template>
+
+  <xsl:template match="form">
+    <xsl:apply-templates/><br/>
+  </xsl:template>
+
+  <xsl:template match="orth">
+    <font class="orth"><xsl:apply-templates/></font>
+  </xsl:template>
+
+  <xsl:template match="pron">
+    <font class="pron"><xsl:apply-templates/></font>
+  </xsl:template>
+
+  <xsl:template match="etym">
+    <font class="etym"><xsl:apply-templates/></font>
+  </xsl:template>
+
+  <xsl:template match="def">
+    <font class="def"><xsl:apply-templates/></font>
+  </xsl:template>
+
+  <xsl:template match="usg">
+    <font class="usg"><xsl:apply-templates/></font>
+  </xsl:template>
+
+  <xsl:template match="@xml:lang">
+    <xsl:variable name="dir">
+      <xsl:if test="@xml:lang">
+        <xsl:call-template name="getDirection">
+         <xsl:with-param name="lang"><xsl:value-of select="@xml:lang"/></xsl:with-param>
+        </xsl:call-template>
+      </xsl:if>
+    </xsl:variable>
+    <xsl:if test="$dir">
+      <xsl:attribute name="dir">
+        <xsl:value-of select="$dir"/>
+      </xsl:attribute>
+    </xsl:if>
+  </xsl:template>
+
+  <!-- If the parent of the text is a verse then, we need to wrap in span. This applies
+  to any punctuation really, since all other words should be contained in a W  -->
+  <xsl:template match="text()">
+  		<xsl:choose>
+	  		<xsl:when test="name(..) = 'verse' and normalize-space(.) != ''"><span class="w"><span class="text"><xsl:value-of select="."/></span></span></xsl:when>
+	  		<xsl:when test="normalize-space(.) != ''"><xsl:value-of select="."/></xsl:when>
+  		</xsl:choose>
+  </xsl:template>
+
+
+  <xsl:template match="text()" mode="small-caps">
+  <xsl:value-of select="translate(., 'abcdefghijklmnopqrstuvwxyz', 'ABCDEFGHIJKLMNOPQRSTUVWXYZ')"/>
+  </xsl:template>
+
+  <!--
+    The direction is deduced from the xml:lang attribute and is assumed to be meaningful for those elements.
+    Note: there is a bug that prevents dir=rtl from working.
+    see: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4296022 and 4866977
+  -->
+  <xsl:template name="getDirection">
+    <xsl:param name="lang"/>
+    <xsl:choose>
+      <xsl:when test="$lang = 'he' or $lang = 'ar' or $lang = 'fa' or $lang = 'ur' or $lang = 'syr'">
+        <xsl:value-of select="'rtl'"/>
+      </xsl:when>
+      <xsl:otherwise>
+        <xsl:value-of select="'ltr'"/>
+      </xsl:otherwise>
+    </xsl:choose>
+   </xsl:template>
+   
+	<xsl:template name="string-replace-all">
+	<xsl:param name="text" />
+	<xsl:param name="replace" />
+	<xsl:param name="by" />
+	<xsl:choose>
+		<xsl:when test="contains($text, $replace)">
+			<xsl:value-of select="substring-before($text,$replace)" />
+			<xsl:value-of select="$by" />
+			<xsl:call-template name="string-replace-all">
+				<xsl:with-param name="text" select="substring-after($text,$replace)" />
+				<xsl:with-param name="replace" select="$replace" />
+				<xsl:with-param name="by" select="$by" />
+			</xsl:call-template>
+		</xsl:when>
+		<xsl:otherwise>
+			<xsl:value-of select="$text" />
+		</xsl:otherwise>
+	</xsl:choose>
+</xsl:template>  
+</xsl:stylesheet>

Added: trunk/step/step-core/src/main/resources/log4j.properties
===================================================================
--- trunk/step/step-core/src/main/resources/log4j.properties	                        (rev 0)
+++ trunk/step/step-core/src/main/resources/log4j.properties	2010-11-21 21:46:24 UTC (rev 188)
@@ -0,0 +1,13 @@
+# Set root logger level to DEBUG and its only appender to A1.
+log4j.rootLogger=WARN, A1
+
+# A1 is set to be a ConsoleAppender.
+log4j.appender.A1=org.apache.log4j.ConsoleAppender
+log4j.appender.A1.layout=org.apache.log4j.PatternLayout
+log4j.appender.A1.layout.ConversionPattern=%-15.15c(%-5p) %m%n
+
+
+# Categories
+org.crosswire.jsword.book.sword.ConfigEntry=WARN
+log4j.category.com.tyndalehouse.step=DEBUG
+

Modified: trunk/step/step-core/src/test/java/com/tyndalehouse/step/core/service/JSwordServiceImplTest.java
===================================================================
--- trunk/step/step-core/src/test/java/com/tyndalehouse/step/core/service/JSwordServiceImplTest.java	2010-11-15 20:29:03 UTC (rev 187)
+++ trunk/step/step-core/src/test/java/com/tyndalehouse/step/core/service/JSwordServiceImplTest.java	2010-11-21 21:46:24 UTC (rev 188)
@@ -37,8 +37,8 @@
      */
     @Test
     public void testInterlinearTransformation() throws Exception {
-        final Book currentBook = Books.installed().getBook("esv");
-        final BookData bookData = new BookData(currentBook, currentBook.getKey("Romans 1"));
+        final Book currentBook = Books.installed().getBook("ChiUns");
+        final BookData bookData = new BookData(currentBook, currentBook.getKey("Romans 1-2"));
         final Element osisFragment = bookData.getOsisFragment();
 
         final XMLOutputter xmlOutputter = new XMLOutputter(Format.getPrettyFormat());
@@ -49,7 +49,7 @@
         final ArrayList<LookupOption> options = new ArrayList<LookupOption>();
         options.add(INTERLINEAR);
 
-        final String osisText = jsi.getOsisText("KJV", "Romans 1:4", options, "");
+        final String osisText = jsi.getOsisText("ChiUns", "Romans 1-2", options, "");
         final SAXBuilder sb = new SAXBuilder();
         final Document d = sb.build(new StringReader(osisText));
 

Added: trunk/step/step-core/src/test/java/com/tyndalehouse/step/core/utils/StringConversionUtilsTest.java
===================================================================
--- trunk/step/step-core/src/test/java/com/tyndalehouse/step/core/utils/StringConversionUtilsTest.java	                        (rev 0)
+++ trunk/step/step-core/src/test/java/com/tyndalehouse/step/core/utils/StringConversionUtilsTest.java	2010-11-21 21:46:24 UTC (rev 188)
@@ -0,0 +1,20 @@
+package com.tyndalehouse.step.core.utils;
+
+import static com.tyndalehouse.step.core.utils.StringConversionUtils.getAnyKey;
+import static org.junit.Assert.assertEquals;
+
+import org.junit.Test;
+
+public class StringConversionUtilsTest {
+    @Test
+    public void testGetAnyKey() {
+        assertEquals(getAnyKey("strong:H1"), "1");
+        assertEquals(getAnyKey("strong:H123"), "123");
+        assertEquals(getAnyKey("strong:G1"), "1");
+        assertEquals(getAnyKey("strong:G123"), "123");
+        assertEquals(getAnyKey("G123"), "123");
+        assertEquals(getAnyKey("H123"), "123");
+        assertEquals(getAnyKey("123"), "123");
+        assertEquals(getAnyKey("strong:G00123"), "123");
+    }
+}

Modified: trunk/step/step-parent/pom.xml
===================================================================
--- trunk/step/step-parent/pom.xml	2010-11-15 20:29:03 UTC (rev 187)
+++ trunk/step/step-parent/pom.xml	2010-11-21 21:46:24 UTC (rev 188)
@@ -10,7 +10,7 @@
 	<properties>
 		<project.build.sourceEncoding>iso-8859-1</project.build.sourceEncoding>
 		<project.reporting.outputEncoding>iso-8859-1</project.reporting.outputEncoding>
-		<java.version>1.5</java.version>
+		<java.version>1.6</java.version>
 
 		<db.directory>${user.home}/TyndaleStep/StepDB</db.directory>
 		<db.driver>org.apache.derby.jdbc.EmbeddedDriver</db.driver>

Modified: trunk/step/step-web/src/main/webapp/css/initial-fonts.css
===================================================================
--- trunk/step/step-web/src/main/webapp/css/initial-fonts.css	2010-11-15 20:29:03 UTC (rev 187)
+++ trunk/step/step-web/src/main/webapp/css/initial-fonts.css	2010-11-21 21:46:24 UTC (rev 188)
@@ -21,6 +21,7 @@
 	font-size: xx-small;
 }
 
-.toolbarContainer span {
+.toolbarContainer label {
 	font-size: x-small;
+	padding: 0px 3px 0px 3px;
 }
\ No newline at end of file

Modified: trunk/step/step-web/src/main/webapp/css/initial-layout.css
===================================================================
--- trunk/step/step-web/src/main/webapp/css/initial-layout.css	2010-11-15 20:29:03 UTC (rev 187)
+++ trunk/step/step-web/src/main/webapp/css/initial-layout.css	2010-11-21 21:46:24 UTC (rev 188)
@@ -8,6 +8,15 @@
 	background: #F6F6F6;
 }
 
+.ui-button-text {
+	padding: 1px 0px 1px 0px !important;
+}
+
+.no-left-border {
+	/* border-left: none; */
+	margin-left: -1px; 
+}
+
 .bookmarksContent {
 	background: #EEF;
 }
@@ -48,12 +57,14 @@
 
 .toolbarContainer {
 	display: none;
+	margin-top: 3px;
 	margin-bottom: 3px;
 	text-align: left;
+	padding: 3px;
 }
 
-.toolbarContainer {
-	padding: 5px;
+.toolbarContainer label {
+	margin-right: 3px;
 }
 
 .inactive {

Modified: trunk/step/step-web/src/main/webapp/css/passage.css
===================================================================
--- trunk/step/step-web/src/main/webapp/css/passage.css	2010-11-15 20:29:03 UTC (rev 187)
+++ trunk/step/step-web/src/main/webapp/css/passage.css	2010-11-21 21:46:24 UTC (rev 188)
@@ -44,25 +44,24 @@
 	text-decoration: none;
 }
 
-A.strongs {
-	color: black;
-	text-decoration: none;
+span.w {
+	margin-top: 20px;	
 }
 
-SUB.strongs {
-	font-size: 75%;
-	color: red;
+span.strongs a {
+	color: orange;
+	text-decoration: none;
+	font-size: xx-small;
+	text-align: center;
 }
 
-SUB.morph {
-	font-size: 75%;
-	color: blue;
+span.morphs a {
+	color: green;
+	text-decoration: none;
+	font-size: xx-small;
+	text-align: center;
 }
 
-SUB.lemma {
-	font-size: 75%;
-	color: red;
-}
 
 SUP.verseNumber {
 	font-size: 75%;
@@ -110,32 +109,38 @@
 	text-align: center;
 	font-size: 115%;
 	color: #000000;
+	clear: both;
 }
 
 H2.level {
 	text-align: center;
 	font-size: 110%;
 	color: #000000;
+	clear: both;
 }
 
 H3.level {
 	text-align: center;
 	font-size: 100%;
+	clear: both;
 }
 
 H4.level {
 	text-align: center;
 	font-size: 90%;
+	clear: both;
 }
 
 H5.level {
 	text-align: center;
 	font-size: 85%;
+	clear: both;
 }
 
 H6.level {
 	text-align: center;
 	font-size: 80%;
+	clear: both;
 }
 
 H3.heading {
@@ -143,12 +148,14 @@
 	color: #666699;
 	font-weight: bold;
 	clear: both;
+	clear: both;
 }
 
 H2.heading {
 	font-size: 115%;
 	color: #669966;
 	font-weight: bold;
+	clear: both;
 }
 
 div.margin {

Modified: trunk/step/step-web/src/main/webapp/index.jsp
===================================================================
--- trunk/step/step-web/src/main/webapp/index.jsp	2010-11-15 20:29:03 UTC (rev 187)
+++ trunk/step/step-web/src/main/webapp/index.jsp	2010-11-21 21:46:24 UTC (rev 188)
@@ -14,10 +14,10 @@
     <script src="libs/jquery-1.4.2.min.js" type="text/javascript"></script>
     <script src="libs/jquery-ui-1.8.5.custom.min.js" type="text/javascript"></script>
     <script src="libs/jquery.layout-latest.js" type="text/javascript"></script>
+    <script src="js/util.js" type="text/javascript"></script>
     <script src="js/passage_toolbar.js" type="text/javascript"></script>
     <script src="js/passage.js" type="text/javascript"></script>
     <script src="js/init.js" type="text/javascript"></script>
-    
 </HEAD>
 <body>
 
@@ -25,8 +25,7 @@
 <div class="passageContainer leftPassage">
 	<div>
 	    <input class="passageVersion defaultValue" type="text" value="Select a Bible version, e.g. ESV" />
-	    <input class="passageReference defaultValue" type="text"  value="Select a reference, e.g. Gen 1:1" />
-	    <button class="searchButton">Search</button>
+	    <input class="passageReference defaultValue" type="text"  value="Select a reference, e.g. Gen 1:1" /><button class="searchButton">Search</button>
 	    <input id="leftCheck" type="checkbox" class="toolbarButton"><label for="leftCheck">Toolbar</label></input>
 	</div>
 
@@ -47,8 +46,7 @@
 <div class="passageContainer rightPassage">
 	<div>
 	    <input class="passageVersion defaultValue" type="text" value="Select a Bible version, e.g. ESV" />
-	    <input class="passageReference defaultValue" type="text"  value="Select a reference, e.g. Gen 1:1" />
-	    <button class="searchButton">Search</button>
+	    <input class="passageReference defaultValue" type="text"  value="Select a reference, e.g. Gen 1:1" /><button class="searchButton">Search</button>
 	    <input id="rightCheck" type="checkbox" class="toolbarButton"><label for="rightCheck">Toolbar</label></input>
 	</div>
 

Modified: trunk/step/step-web/src/main/webapp/js/bookmark.js
===================================================================
--- trunk/step/step-web/src/main/webapp/js/bookmark.js	2010-11-15 20:29:03 UTC (rev 187)
+++ trunk/step/step-web/src/main/webapp/js/bookmark.js	2010-11-21 21:46:24 UTC (rev 188)
@@ -3,6 +3,61 @@
  * The bookmarks components record events that are happening across the application,
  * for e.g. passage changes, but will also show related information to the passage.
  */
-function Bookmark() {
-	//TODO
-}
\ No newline at end of file
+function Bookmark(bookmarkContainer) {
+	this.bookmarkContainer = bookmarkContainer;
+	
+	//for bookmarks, we will only have a few, therefore we store them in an array for now:
+	//we will store the elements in here, with their jquery wrapper
+	this.currentBookmarks = [];
+}
+//
+///**
+// * Adding a bookmark
+// */
+//Bookmark.prototype.add = function(passageReference) {
+//	var bookmark = this.get(passageReference);
+//	if(bookmark) {
+//		//move bookmark around
+//		
+//		return;
+//	}
+//	
+//	//otherwise we create the bookmark
+//	bookmark = "<span class='bookmark'>" +
+//			"<a href='#left-" + passageReference + "' >" + "left-arrow" +"</a>" +
+//			passageReference +
+//			"<a href='#right-" + passageReference + "' >" + "right-arrow" +"</a>" +;
+//	
+//	$(this.bookmarkContainer).append(bookmark);
+//	
+//	//insert bookmark here => i.e. it would be good to have a linked list implementation? (or perhaps, 
+//	//we insert whatever...
+//	this.currentBookmarks.insert(bookmark);
+//}
+//
+///**
+// * gets a bookmark
+// */
+//Bookmark.prototype.get = function(passageReference) {
+//	//TODO check this
+//	return $("val() = " + passageReference, this.bookmarkContainer);
+////or
+//	/*
+//	var i = 0;
+//	for(i = 0; i < this.currentBookmarks.length; i++) {
+//		if(this.currentBookmarks[i].val() = passageReference) {
+//			return this.currentBookmarks[i];
+//		}
+//	}*/
+//}
+//
+///** 
+// * removes a bookmark from the list
+// */
+//Bookmark.prototype.remove(reference) {
+//	var b = getBookmark(reference);
+//	if(b) {
+//		b.removeFromParent();
+//	}
+//}
+

Modified: trunk/step/step-web/src/main/webapp/js/init.js
===================================================================
--- trunk/step/step-web/src/main/webapp/js/init.js	2010-11-15 20:29:03 UTC (rev 187)
+++ trunk/step/step-web/src/main/webapp/js/init.js	2010-11-21 21:46:24 UTC (rev 188)
@@ -103,7 +103,9 @@
 	//get data for passages
 	// make call to server first and once, to cache all passages:
 	var strongedVersions = [];
-	var ii = 0;
+
+	//we reserve the first spot for "ALL Versions"
+	var ii = 1;
 	
 	$.getJSON("rest/bible/versions", function(data) {
 		var parsedResponse = $.map(data, function(item) {
@@ -121,10 +123,20 @@
 			}
 		});
 		
+		//add the ALL Version, by iterating through all found versions and adding them as the value
+		var allVersionsKey = "";
+		for(var jj = 1; jj < ii; jj++) {
+			allVersionsKey += strongedVersions[jj].value;
+			if(jj + 1 < ii) {
+				allVersionsKey += ',';
+			}
+		}
+		strongedVersions[0] = {label: "All available versions", value: allVersionsKey };
+
 		
 		//set up initial passages with reference data:
-		var versions = ["ESV" ];
-		var passages = ["Romans 1"];
+		var versions = ["KJV" ];
+		var passages = ["Romans 1:1-3"];
 		$(".passageContainer").each(
 				function(index) {
 					var passage = new Passage(this, parsedResponse);

Modified: trunk/step/step-web/src/main/webapp/js/passage.js
===================================================================
--- trunk/step/step-web/src/main/webapp/js/passage.js	2010-11-15 20:29:03 UTC (rev 187)
+++ trunk/step/step-web/src/main/webapp/js/passage.js	2010-11-21 21:46:24 UTC (rev 188)
@@ -15,7 +15,10 @@
 	$(".searchButton", passageContainer).button({
 		icons: { primary: "ui-icon-search" }, 
 		text: false
-	}).click(function() {
+	})
+	.removeClass( "ui-corner-all" )
+	.addClass( "ui-corner-right ui-button-icon no-left-border" )
+	.click(function() {
 		self.changePassage();
 	});
 	
@@ -46,11 +49,12 @@
 		this.select();
 	});
 	
+	//set up dropdown button next to it
+	addButtonToAutoComplete(this.version, "ui-icon-triangle-1-s");
+	
 	//set up blur for textbox
 	this.reference.change(function(){
 		self.changePassage();
-	}).focus(function() {
-		this.select();
 	});
 }
 

Modified: trunk/step/step-web/src/main/webapp/js/passage_toolbar.js
===================================================================
--- trunk/step/step-web/src/main/webapp/js/passage_toolbar.js	2010-11-15 20:29:03 UTC (rev 187)
+++ trunk/step/step-web/src/main/webapp/js/passage_toolbar.js	2010-11-21 21:46:24 UTC (rev 188)
@@ -35,6 +35,13 @@
 	});
 }
 
+//function split( val ) {
+//	return val.split( /,\s*/ );
+//}
+function extractLast( term ) {
+	return split( term ).pop();
+}
+
 Toolbar.prototype.createInterlinearDropdown = function(toolbarId, strongedVersions, interlinearButton) {
 	this.toolbarContainer.append("<input id='interlinear" + toolbarId
 			+ "' type='text' class='interlinearVersion' value='Interlinear version' disabled='disabled' />");
@@ -46,7 +53,17 @@
 		minLength : 0,
 		delay: 0,
 		select : function(event, ui) {
-			$(this).val(ui.item.value);
+			var terms = this.value.split( /,\s*/ );
+			
+			// remove the current input
+			terms.pop();
+			
+			// add the selected item
+			terms.push( ui.item.value );
+			
+			// add placeholder to get the comma-and-space at the end
+			terms.push( "" );
+			this.value = terms.join( ", " );
 			self.passage.changePassage();
 			return false;
 		}
@@ -54,6 +71,31 @@
 	
 	addDefaultValue(interlinearSelector);
 	
+	//todo, make utility function
+	//set up dropdown button next to it
+	$( "<button>&nbsp;</button>" ).attr( "tabIndex", -1 )
+	.attr( "title", "Show all Bible versions" )
+	.insertAfter( interlinearSelector )
+	.button({
+		icons: {
+			primary: "ui-icon-triangle-1-s"
+		},
+		text: false
+	})
+	.removeClass( "ui-corner-all" )
+	.addClass( "ui-corner-right ui-button-icon no-left-border" )
+	.click(function() {
+		// close if already visible
+		if ( interlinearSelector.autocomplete( "widget" ).is( ":visible" ) ) {
+			interlinearSelector.autocomplete( "close" );
+			return;
+		}
+
+		// pass empty string as value to search for, displaying all results
+		interlinearSelector.autocomplete( "search", "" );
+		interlinearSelector.focus();
+	});
+	
 	interlinearButton.click(function() {
 		if($(this).attr('checked')) {
 			interlinearSelector.removeAttr("disabled");

Modified: trunk/step/step-web/src/main/webapp/js/util.js
===================================================================
--- trunk/step/step-web/src/main/webapp/js/util.js	2010-11-15 20:29:03 UTC (rev 187)
+++ trunk/step/step-web/src/main/webapp/js/util.js	2010-11-21 21:46:24 UTC (rev 188)
@@ -0,0 +1,30 @@
+
+/**
+ * adds a button next to a specified element
+ * @param textbox the box to which to add the dropdown button
+ * @param icon the icon to stylise the button
+ */
+function addButtonToAutoComplete(textbox, icon) {
+	$( "<button>&nbsp;</button>" ).attr( "tabIndex", -1 )
+	.attr( "title", "Show all Bible versions" )
+	.insertAfter( textbox )
+	.button({
+		icons: {
+			primary: icon
+		},
+		text: false
+	})
+	.removeClass( "ui-corner-all" )
+	.addClass( "ui-corner-right ui-button-icon no-left-border" )
+	.click(function() {
+		// close if already visible
+		if ( textbox.autocomplete( "widget" ).is( ":visible" ) ) {
+			textbox.autocomplete( "close" );
+			return;
+		}
+
+		// pass empty string as value to search for, displaying all results
+		textbox.autocomplete( "search", "" );
+		textbox.focus();
+	});
+}
\ No newline at end of file




More information about the Tynstep-svn mailing list