1*8c35d5eeSXin Li<xsl:stylesheet version="1.0" 2*8c35d5eeSXin Lixmlns:xsl="http://www.w3.org/1999/XSL/Transform" 3*8c35d5eeSXin Lixmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" 4*8c35d5eeSXin Lixmlns:dc="http://purl.org/dc/elements/1.1/" 5*8c35d5eeSXin Lixmlns:dcq="http://purl.org/dc/qualifiers/1.0/" 6*8c35d5eeSXin Lixmlns:fo="http://www.w3.org/1999/XSL/Format" 7*8c35d5eeSXin Lixmlns:fn="http://www.w3.org/2005/xpath-functions"> 8*8c35d5eeSXin Li <xsl:output method="html"/> 9*8c35d5eeSXin Li <!-- Set to 1 to show explanations by default. Set to 0 to hide them --> 10*8c35d5eeSXin Li <xsl:variable name="show_explanation_default" select="0" /> 11*8c35d5eeSXin Li <!-- The characters within the Webdings font that show the triangles --> 12*8c35d5eeSXin Li <xsl:variable name="show_button_text" select="'▶'" /> 13*8c35d5eeSXin Li <xsl:variable name="hide_button_text" select="'▽'" /> 14*8c35d5eeSXin Li <!-- The suffix for names --> 15*8c35d5eeSXin Li <xsl:variable name="button_suffix" select="'__button'"/> 16*8c35d5eeSXin Li <xsl:variable name="body_suffix" select="'__body'"/> 17*8c35d5eeSXin Li <!-- For easy reference, the name of the button --> 18*8c35d5eeSXin Li <xsl:variable name="show_hide_all_button" select="'show_hide_all_button'"/> 19*8c35d5eeSXin Li 20*8c35d5eeSXin Li <!-- The top-level element --> 21*8c35d5eeSXin Li <xsl:template match="GUIDE"> 22*8c35d5eeSXin Li <HTML> 23*8c35d5eeSXin Li <HEAD> 24*8c35d5eeSXin Li <TITLE><xsl:value-of select="@title"/></TITLE> 25*8c35d5eeSXin Li <META http-equiv="Content-Type" content="text/html; charset=utf-8"/> 26*8c35d5eeSXin Li <LINK HREF="https://www.google.com/favicon.ico" type="image/x-icon" 27*8c35d5eeSXin Li rel="shortcut icon"/> 28*8c35d5eeSXin Li <LINK HREF="styleguide.css" 29*8c35d5eeSXin Li type="text/css" rel="stylesheet"/> 30*8c35d5eeSXin Li 31*8c35d5eeSXin Li <SCRIPT language="javascript" type="text/javascript"> 32*8c35d5eeSXin Li 33*8c35d5eeSXin Li function GetElementsByName(name) { 34*8c35d5eeSXin Li // Workaround a bug on old versions of opera. 35*8c35d5eeSXin Li if (document.getElementsByName) { 36*8c35d5eeSXin Li return document.getElementsByName(name); 37*8c35d5eeSXin Li } else { 38*8c35d5eeSXin Li return [document.getElementById(name)]; 39*8c35d5eeSXin Li } 40*8c35d5eeSXin Li } 41*8c35d5eeSXin Li 42*8c35d5eeSXin Li /** 43*8c35d5eeSXin Li * @param {string} namePrefix The prefix of the body name. 44*8c35d5eeSXin Li * @param {function(boolean): boolean} getVisibility Computes the new 45*8c35d5eeSXin Li * visibility state, given the current one. 46*8c35d5eeSXin Li */ 47*8c35d5eeSXin Li function ChangeVisibility(namePrefix, getVisibility) { 48*8c35d5eeSXin Li var bodyName = namePrefix + '<xsl:value-of select="$body_suffix"/>'; 49*8c35d5eeSXin Li var buttonName = namePrefix + '<xsl:value-of select="$button_suffix"/>'; 50*8c35d5eeSXin Li var bodyElements = GetElementsByName(bodyName); 51*8c35d5eeSXin Li var linkElement = GetElementsByName('link-' + buttonName)[0]; 52*8c35d5eeSXin Li if (bodyElements.length != 1) { 53*8c35d5eeSXin Li throw Error('ShowHideByName() got the wrong number of bodyElements: ' + 54*8c35d5eeSXin Li bodyElements.length); 55*8c35d5eeSXin Li } else { 56*8c35d5eeSXin Li var bodyElement = bodyElements[0]; 57*8c35d5eeSXin Li var buttonElement = GetElementsByName(buttonName)[0]; 58*8c35d5eeSXin Li var isVisible = bodyElement.style.display != "none"; 59*8c35d5eeSXin Li if (getVisibility(isVisible)) { 60*8c35d5eeSXin Li bodyElement.style.display = "inline"; 61*8c35d5eeSXin Li linkElement.style.display = "block"; 62*8c35d5eeSXin Li buttonElement.innerHTML = '<xsl:value-of select="$hide_button_text"/>'; 63*8c35d5eeSXin Li } else { 64*8c35d5eeSXin Li bodyElement.style.display = "none"; 65*8c35d5eeSXin Li linkElement.style.display = "none"; 66*8c35d5eeSXin Li buttonElement.innerHTML = '<xsl:value-of select="$show_button_text"/>'; 67*8c35d5eeSXin Li } 68*8c35d5eeSXin Li } 69*8c35d5eeSXin Li } 70*8c35d5eeSXin Li 71*8c35d5eeSXin Li function ShowHideByName(namePrefix) { 72*8c35d5eeSXin Li ChangeVisibility(namePrefix, function(old) { return !old; }); 73*8c35d5eeSXin Li } 74*8c35d5eeSXin Li 75*8c35d5eeSXin Li function ShowByName(namePrefix) { 76*8c35d5eeSXin Li ChangeVisibility(namePrefix, function() { return true; }); 77*8c35d5eeSXin Li } 78*8c35d5eeSXin Li 79*8c35d5eeSXin Li function ShowHideAll() { 80*8c35d5eeSXin Li var allButton = GetElementsByName("show_hide_all_button")[0]; 81*8c35d5eeSXin Li if (allButton.innerHTML == '<xsl:value-of select="$hide_button_text"/>') { 82*8c35d5eeSXin Li allButton.innerHTML = '<xsl:value-of select="$show_button_text"/>'; 83*8c35d5eeSXin Li SetHiddenState(document.getElementsByTagName("body")[0].childNodes, "none", '<xsl:value-of select="$show_button_text"/>'); 84*8c35d5eeSXin Li } else { 85*8c35d5eeSXin Li allButton.innerHTML = '<xsl:value-of select="$hide_button_text"/>'; 86*8c35d5eeSXin Li SetHiddenState(document.getElementsByTagName("body")[0].childNodes, "inline", '<xsl:value-of select="$hide_button_text"/>'); 87*8c35d5eeSXin Li } 88*8c35d5eeSXin Li } 89*8c35d5eeSXin Li 90*8c35d5eeSXin Li // Recursively sets state of all children 91*8c35d5eeSXin Li // of a particular node. 92*8c35d5eeSXin Li function SetHiddenState(root, newState, newButton) { 93*8c35d5eeSXin Li for (var i = 0; i != root.length; i++) { 94*8c35d5eeSXin Li SetHiddenState(root[i].childNodes, newState, newButton); 95*8c35d5eeSXin Li if (root[i].className == 'showhide_button') { 96*8c35d5eeSXin Li root[i].innerHTML = newButton; 97*8c35d5eeSXin Li } 98*8c35d5eeSXin Li if (root[i].className == 'stylepoint_body' || 99*8c35d5eeSXin Li root[i].className == 'link_button') { 100*8c35d5eeSXin Li root[i].style.display = newState; 101*8c35d5eeSXin Li } 102*8c35d5eeSXin Li } 103*8c35d5eeSXin Li } 104*8c35d5eeSXin Li 105*8c35d5eeSXin Li 106*8c35d5eeSXin Li function EndsWith(str, suffix) { 107*8c35d5eeSXin Li var l = str.length - suffix.length; 108*8c35d5eeSXin Li return l >= 0 && str.indexOf(suffix, l) == l; 109*8c35d5eeSXin Li } 110*8c35d5eeSXin Li 111*8c35d5eeSXin Li function RefreshVisibilityFromHashParam() { 112*8c35d5eeSXin Li var hashRegexp = new RegExp('#([^&#]*)$'); 113*8c35d5eeSXin Li var hashMatch = hashRegexp.exec(window.location.href); 114*8c35d5eeSXin Li var anchor = hashMatch && GetElementsByName(hashMatch[1])[0]; 115*8c35d5eeSXin Li var node = anchor; 116*8c35d5eeSXin Li var suffix = '<xsl:value-of select="$body_suffix"/>'; 117*8c35d5eeSXin Li while (node) { 118*8c35d5eeSXin Li var id = node.id; 119*8c35d5eeSXin Li var matched = id && EndsWith(id, suffix); 120*8c35d5eeSXin Li if (matched) { 121*8c35d5eeSXin Li var len = id.length - suffix.length; 122*8c35d5eeSXin Li ShowByName(id.substring(0, len)); 123*8c35d5eeSXin Li if (anchor.scrollIntoView) { 124*8c35d5eeSXin Li anchor.scrollIntoView(); 125*8c35d5eeSXin Li } 126*8c35d5eeSXin Li 127*8c35d5eeSXin Li return; 128*8c35d5eeSXin Li } 129*8c35d5eeSXin Li node = node.parentNode; 130*8c35d5eeSXin Li } 131*8c35d5eeSXin Li } 132*8c35d5eeSXin Li 133*8c35d5eeSXin Li window.onhashchange = RefreshVisibilityFromHashParam; 134*8c35d5eeSXin Li 135*8c35d5eeSXin Li window.onload = function() { 136*8c35d5eeSXin Li // if the URL contains "?showall=y", expand the details of all children 137*8c35d5eeSXin Li var showHideAllRegex = new RegExp("[\\?&](showall)=([^&#]*)"); 138*8c35d5eeSXin Li var showHideAllValue = showHideAllRegex.exec(window.location.href); 139*8c35d5eeSXin Li if (showHideAllValue != null) { 140*8c35d5eeSXin Li if (showHideAllValue[2] == "y") { 141*8c35d5eeSXin Li SetHiddenState(document.getElementsByTagName("body")[0].childNodes, 142*8c35d5eeSXin Li "inline", '<xsl:value-of select="$hide_button_text"/>'); 143*8c35d5eeSXin Li } else { 144*8c35d5eeSXin Li SetHiddenState(document.getElementsByTagName("body")[0].childNodes, 145*8c35d5eeSXin Li "none", '<xsl:value-of select="$show_button_text"/>'); 146*8c35d5eeSXin Li } 147*8c35d5eeSXin Li } 148*8c35d5eeSXin Li var showOneRegex = new RegExp("[\\?&](showone)=([^&#]*)"); 149*8c35d5eeSXin Li var showOneValue = showOneRegex.exec(window.location.href); 150*8c35d5eeSXin Li if (showOneValue) { 151*8c35d5eeSXin Li ShowHideByName(showOneValue[2]); 152*8c35d5eeSXin Li } 153*8c35d5eeSXin Li 154*8c35d5eeSXin Li 155*8c35d5eeSXin Li RefreshVisibilityFromHashParam(); 156*8c35d5eeSXin Li } 157*8c35d5eeSXin Li </SCRIPT> 158*8c35d5eeSXin Li </HEAD> 159*8c35d5eeSXin Li <BODY> 160*8c35d5eeSXin Li <H1><xsl:value-of select="@title"/></H1> 161*8c35d5eeSXin Li <xsl:apply-templates/> 162*8c35d5eeSXin Li </BODY> 163*8c35d5eeSXin Li </HTML> 164*8c35d5eeSXin Li </xsl:template> 165*8c35d5eeSXin Li 166*8c35d5eeSXin Li <xsl:template match="OVERVIEW"> 167*8c35d5eeSXin Li <xsl:variable name="button_text"> 168*8c35d5eeSXin Li <xsl:choose> 169*8c35d5eeSXin Li <xsl:when test="$show_explanation_default"> 170*8c35d5eeSXin Li <xsl:value-of select="$hide_button_text"/> 171*8c35d5eeSXin Li </xsl:when> 172*8c35d5eeSXin Li <xsl:otherwise> 173*8c35d5eeSXin Li <xsl:value-of select="$show_button_text"/> 174*8c35d5eeSXin Li </xsl:otherwise> 175*8c35d5eeSXin Li </xsl:choose> 176*8c35d5eeSXin Li </xsl:variable> 177*8c35d5eeSXin Li <DIV style="margin-left: 50%; font-size: 75%;"> 178*8c35d5eeSXin Li <P> 179*8c35d5eeSXin Li Each style point has a summary for which additional information is available 180*8c35d5eeSXin Li by toggling the accompanying arrow button that looks this way: 181*8c35d5eeSXin Li <SPAN class="showhide_button" style="margin-left: 0; float: none"> 182*8c35d5eeSXin Li <xsl:value-of select="$show_button_text"/></SPAN>. 183*8c35d5eeSXin Li You may toggle all summaries with the big arrow button: 184*8c35d5eeSXin Li </P> 185*8c35d5eeSXin Li <DIV style=" font-size: larger; margin-left: +2em;"> 186*8c35d5eeSXin Li <SPAN class="showhide_button" style="font-size: 180%; float: none"> 187*8c35d5eeSXin Li <xsl:attribute name="onclick"><xsl:value-of select="'javascript:ShowHideAll()'"/></xsl:attribute> 188*8c35d5eeSXin Li <xsl:attribute name="name"><xsl:value-of select="$show_hide_all_button"/></xsl:attribute> 189*8c35d5eeSXin Li <xsl:attribute name="id"><xsl:value-of select="$show_hide_all_button"/></xsl:attribute> 190*8c35d5eeSXin Li <xsl:value-of select="$button_text"/> 191*8c35d5eeSXin Li </SPAN> 192*8c35d5eeSXin Li Toggle all summaries 193*8c35d5eeSXin Li </DIV> 194*8c35d5eeSXin Li </DIV> 195*8c35d5eeSXin Li <xsl:call-template name="TOC"> 196*8c35d5eeSXin Li <xsl:with-param name="root" select=".."/> 197*8c35d5eeSXin Li </xsl:call-template> 198*8c35d5eeSXin Li <xsl:apply-templates/> 199*8c35d5eeSXin Li </xsl:template> 200*8c35d5eeSXin Li 201*8c35d5eeSXin Li <xsl:template match="PARTING_WORDS"> 202*8c35d5eeSXin Li <H2>Parting Words</H2> 203*8c35d5eeSXin Li <xsl:apply-templates/> 204*8c35d5eeSXin Li </xsl:template> 205*8c35d5eeSXin Li 206*8c35d5eeSXin Li <xsl:template match="CATEGORY"> 207*8c35d5eeSXin Li <DIV> 208*8c35d5eeSXin Li <xsl:attribute name="class"><xsl:value-of select="@class"/></xsl:attribute> 209*8c35d5eeSXin Li <H2> 210*8c35d5eeSXin Li <xsl:variable name="category_name"> 211*8c35d5eeSXin Li <xsl:call-template name="anchorname"> 212*8c35d5eeSXin Li <xsl:with-param name="sectionname" select="@title"/> 213*8c35d5eeSXin Li </xsl:call-template> 214*8c35d5eeSXin Li </xsl:variable> 215*8c35d5eeSXin Li <xsl:attribute name="name"><xsl:value-of select="$category_name"/></xsl:attribute> 216*8c35d5eeSXin Li <xsl:attribute name="id"><xsl:value-of select="$category_name"/></xsl:attribute> 217*8c35d5eeSXin Li <xsl:value-of select="@title"/> 218*8c35d5eeSXin Li </H2> 219*8c35d5eeSXin Li <xsl:apply-templates/> 220*8c35d5eeSXin Li </DIV> 221*8c35d5eeSXin Li </xsl:template> 222*8c35d5eeSXin Li 223*8c35d5eeSXin Li <xsl:template match="STYLEPOINT"> 224*8c35d5eeSXin Li <DIV> 225*8c35d5eeSXin Li <xsl:attribute name="class"><xsl:value-of select="@class"/></xsl:attribute> 226*8c35d5eeSXin Li <xsl:variable name="stylepoint_name"> 227*8c35d5eeSXin Li <xsl:call-template name="anchorname"> 228*8c35d5eeSXin Li <xsl:with-param name="sectionname" select="@title"/> 229*8c35d5eeSXin Li </xsl:call-template> 230*8c35d5eeSXin Li </xsl:variable> 231*8c35d5eeSXin Li <xsl:variable name="button_text"> 232*8c35d5eeSXin Li <xsl:choose> 233*8c35d5eeSXin Li <xsl:when test="$show_explanation_default"> 234*8c35d5eeSXin Li <xsl:value-of select="$hide_button_text"/> 235*8c35d5eeSXin Li </xsl:when> 236*8c35d5eeSXin Li <xsl:otherwise> 237*8c35d5eeSXin Li <xsl:value-of select="$show_button_text"/> 238*8c35d5eeSXin Li </xsl:otherwise> 239*8c35d5eeSXin Li </xsl:choose> 240*8c35d5eeSXin Li </xsl:variable> 241*8c35d5eeSXin Li <H3> 242*8c35d5eeSXin Li <A> 243*8c35d5eeSXin Li <xsl:attribute name="name"><xsl:value-of select="$stylepoint_name"/></xsl:attribute> 244*8c35d5eeSXin Li <xsl:attribute name="id"><xsl:value-of select="$stylepoint_name"/></xsl:attribute> 245*8c35d5eeSXin Li <xsl:value-of select="@title"/> 246*8c35d5eeSXin Li </A> 247*8c35d5eeSXin Li </H3> 248*8c35d5eeSXin Li <xsl:variable name="buttonName"> 249*8c35d5eeSXin Li <xsl:value-of select="$stylepoint_name"/><xsl:value-of select="$button_suffix"/> 250*8c35d5eeSXin Li </xsl:variable> 251*8c35d5eeSXin Li <xsl:variable name="onclick_definition"> 252*8c35d5eeSXin Li <xsl:text>javascript:ShowHideByName('</xsl:text> 253*8c35d5eeSXin Li <xsl:value-of select="$stylepoint_name"/> 254*8c35d5eeSXin Li <xsl:text>')</xsl:text> 255*8c35d5eeSXin Li </xsl:variable> 256*8c35d5eeSXin Li <SPAN class="link_button" id="link-{$buttonName}" name="link-{$buttonName}"> 257*8c35d5eeSXin Li <A> 258*8c35d5eeSXin Li <xsl:attribute name="href">?showone=<xsl:value-of select="$stylepoint_name"/>#<xsl:value-of select="$stylepoint_name"/></xsl:attribute> 259*8c35d5eeSXin Li link 260*8c35d5eeSXin Li </A> 261*8c35d5eeSXin Li </SPAN> 262*8c35d5eeSXin Li <SPAN class="showhide_button"> 263*8c35d5eeSXin Li <xsl:attribute name="onclick"><xsl:value-of select="$onclick_definition"/></xsl:attribute> 264*8c35d5eeSXin Li <xsl:attribute name="name"><xsl:value-of select="$buttonName"/></xsl:attribute> 265*8c35d5eeSXin Li <xsl:attribute name="id"><xsl:value-of select="$buttonName"/></xsl:attribute> 266*8c35d5eeSXin Li <xsl:value-of select="$button_text"/> 267*8c35d5eeSXin Li </SPAN> 268*8c35d5eeSXin Li <xsl:apply-templates> 269*8c35d5eeSXin Li <xsl:with-param name="anchor_prefix" select="$stylepoint_name" /> 270*8c35d5eeSXin Li </xsl:apply-templates> 271*8c35d5eeSXin Li </DIV> 272*8c35d5eeSXin Li </xsl:template> 273*8c35d5eeSXin Li 274*8c35d5eeSXin Li <xsl:template match="SUMMARY"> 275*8c35d5eeSXin Li <xsl:param name="anchor_prefix" /> 276*8c35d5eeSXin Li <DIV style="display:inline;"> 277*8c35d5eeSXin Li <xsl:attribute name="class"><xsl:value-of select="@class"/></xsl:attribute> 278*8c35d5eeSXin Li <xsl:apply-templates/> 279*8c35d5eeSXin Li </DIV> 280*8c35d5eeSXin Li </xsl:template> 281*8c35d5eeSXin Li 282*8c35d5eeSXin Li <xsl:template match="BODY"> 283*8c35d5eeSXin Li <xsl:param name="anchor_prefix" /> 284*8c35d5eeSXin Li <DIV> 285*8c35d5eeSXin Li <xsl:attribute name="class"><xsl:value-of select="@class"/></xsl:attribute> 286*8c35d5eeSXin Li <DIV class="stylepoint_body"> 287*8c35d5eeSXin Li <xsl:attribute name="name"><xsl:value-of select="$anchor_prefix"/><xsl:value-of select="$body_suffix"/></xsl:attribute> 288*8c35d5eeSXin Li <xsl:attribute name="id"><xsl:value-of select="$anchor_prefix"/><xsl:value-of select="$body_suffix"/></xsl:attribute> 289*8c35d5eeSXin Li <xsl:attribute name="style"> 290*8c35d5eeSXin Li <xsl:choose> 291*8c35d5eeSXin Li <xsl:when test="$show_explanation_default">display: inline</xsl:when> 292*8c35d5eeSXin Li <xsl:otherwise>display: none</xsl:otherwise> 293*8c35d5eeSXin Li </xsl:choose> 294*8c35d5eeSXin Li </xsl:attribute> 295*8c35d5eeSXin Li <xsl:apply-templates/> 296*8c35d5eeSXin Li </DIV> 297*8c35d5eeSXin Li </DIV> 298*8c35d5eeSXin Li </xsl:template> 299*8c35d5eeSXin Li 300*8c35d5eeSXin Li <xsl:template match="DEFINITION"> 301*8c35d5eeSXin Li <P> 302*8c35d5eeSXin Li <xsl:attribute name="class"><xsl:value-of select="@class"/></xsl:attribute> 303*8c35d5eeSXin Li <SPAN class="stylepoint_section">Definition: </SPAN> 304*8c35d5eeSXin Li <xsl:apply-templates/> 305*8c35d5eeSXin Li </P> 306*8c35d5eeSXin Li </xsl:template> 307*8c35d5eeSXin Li 308*8c35d5eeSXin Li <xsl:template match="PROS"> 309*8c35d5eeSXin Li <P> 310*8c35d5eeSXin Li <xsl:attribute name="class"><xsl:value-of select="@class"/></xsl:attribute> 311*8c35d5eeSXin Li <SPAN class="stylepoint_section">Pros: </SPAN> 312*8c35d5eeSXin Li <xsl:apply-templates/> 313*8c35d5eeSXin Li </P> 314*8c35d5eeSXin Li </xsl:template> 315*8c35d5eeSXin Li 316*8c35d5eeSXin Li <xsl:template match="CONS"> 317*8c35d5eeSXin Li <P> 318*8c35d5eeSXin Li <xsl:attribute name="class"><xsl:value-of select="@class"/></xsl:attribute> 319*8c35d5eeSXin Li <SPAN class="stylepoint_section">Cons: </SPAN> 320*8c35d5eeSXin Li <xsl:apply-templates/> 321*8c35d5eeSXin Li </P> 322*8c35d5eeSXin Li </xsl:template> 323*8c35d5eeSXin Li 324*8c35d5eeSXin Li <xsl:template match="DECISION"> 325*8c35d5eeSXin Li <P> 326*8c35d5eeSXin Li <xsl:attribute name="class"><xsl:value-of select="@class"/></xsl:attribute> 327*8c35d5eeSXin Li <SPAN class="stylepoint_section">Decision: </SPAN> 328*8c35d5eeSXin Li <xsl:apply-templates/> 329*8c35d5eeSXin Li </P> 330*8c35d5eeSXin Li </xsl:template> 331*8c35d5eeSXin Li 332*8c35d5eeSXin Li <xsl:template match="TODO"> 333*8c35d5eeSXin Li <P> 334*8c35d5eeSXin Li <xsl:attribute name="class"><xsl:value-of select="@class"/></xsl:attribute> 335*8c35d5eeSXin Li <DIV style="font-size: 150%;">TODO: 336*8c35d5eeSXin Li <xsl:apply-templates/> 337*8c35d5eeSXin Li </DIV> 338*8c35d5eeSXin Li </P> 339*8c35d5eeSXin Li </xsl:template> 340*8c35d5eeSXin Li 341*8c35d5eeSXin Li <xsl:template match="SUBSECTION"> 342*8c35d5eeSXin Li <P> 343*8c35d5eeSXin Li <xsl:attribute name="class"><xsl:value-of select="@class"/></xsl:attribute> 344*8c35d5eeSXin Li <SPAN class="stylepoint_subsection"><xsl:value-of select="@title"/> </SPAN> 345*8c35d5eeSXin Li <xsl:apply-templates/> 346*8c35d5eeSXin Li </P> 347*8c35d5eeSXin Li </xsl:template> 348*8c35d5eeSXin Li 349*8c35d5eeSXin Li <xsl:template match="SUBSUBSECTION"> 350*8c35d5eeSXin Li <P> 351*8c35d5eeSXin Li <xsl:attribute name="class"><xsl:value-of select="@class"/></xsl:attribute> 352*8c35d5eeSXin Li <SPAN class="stylepoint_subsubsection"><xsl:value-of select="@title"/> </SPAN> 353*8c35d5eeSXin Li <xsl:apply-templates/> 354*8c35d5eeSXin Li </P> 355*8c35d5eeSXin Li </xsl:template> 356*8c35d5eeSXin Li 357*8c35d5eeSXin Li <xsl:template match="CODE_SNIPPET"> 358*8c35d5eeSXin Li <DIV> 359*8c35d5eeSXin Li <xsl:attribute name="class"><xsl:value-of select="@class"/></xsl:attribute> 360*8c35d5eeSXin Li <PRE><xsl:call-template name="print_without_leading_chars"> 361*8c35d5eeSXin Li <xsl:with-param name="text" select="."/> 362*8c35d5eeSXin Li <xsl:with-param name="strip" select="1"/> 363*8c35d5eeSXin Li <xsl:with-param name="is_firstline" select="1"/> 364*8c35d5eeSXin Li <xsl:with-param name="trim_count"> 365*8c35d5eeSXin Li <xsl:call-template name="num_leading_spaces"> 366*8c35d5eeSXin Li <xsl:with-param name="text" select="."/> 367*8c35d5eeSXin Li <xsl:with-param name="max_so_far" select="1000"/> 368*8c35d5eeSXin Li </xsl:call-template> 369*8c35d5eeSXin Li </xsl:with-param> 370*8c35d5eeSXin Li </xsl:call-template></PRE> 371*8c35d5eeSXin Li </DIV> 372*8c35d5eeSXin Li </xsl:template> 373*8c35d5eeSXin Li 374*8c35d5eeSXin Li <xsl:template match="BAD_CODE_SNIPPET"> 375*8c35d5eeSXin Li <DIV> 376*8c35d5eeSXin Li <xsl:attribute name="class"><xsl:value-of select="@class"/></xsl:attribute> 377*8c35d5eeSXin Li <PRE class="badcode"><xsl:call-template name="print_without_leading_chars"> 378*8c35d5eeSXin Li <xsl:with-param name="text" select="."/> 379*8c35d5eeSXin Li <xsl:with-param name="strip" select="1"/> 380*8c35d5eeSXin Li <xsl:with-param name="is_firstline" select="1"/> 381*8c35d5eeSXin Li <xsl:with-param name="trim_count"> 382*8c35d5eeSXin Li <xsl:call-template name="num_leading_spaces"> 383*8c35d5eeSXin Li <xsl:with-param name="text" select="."/> 384*8c35d5eeSXin Li <xsl:with-param name="max_so_far" select="1000"/> 385*8c35d5eeSXin Li </xsl:call-template> 386*8c35d5eeSXin Li </xsl:with-param> 387*8c35d5eeSXin Li </xsl:call-template></PRE> 388*8c35d5eeSXin Li </DIV> 389*8c35d5eeSXin Li </xsl:template> 390*8c35d5eeSXin Li 391*8c35d5eeSXin Li <xsl:template match="PY_CODE_SNIPPET"> 392*8c35d5eeSXin Li <DIV> 393*8c35d5eeSXin Li <xsl:attribute name="class"><xsl:value-of select="@class"/></xsl:attribute> 394*8c35d5eeSXin Li <PRE><xsl:call-template name="print_python_code"> 395*8c35d5eeSXin Li <xsl:with-param name="text" select="."/> 396*8c35d5eeSXin Li </xsl:call-template></PRE> 397*8c35d5eeSXin Li </DIV> 398*8c35d5eeSXin Li </xsl:template> 399*8c35d5eeSXin Li 400*8c35d5eeSXin Li <xsl:template match="BAD_PY_CODE_SNIPPET"> 401*8c35d5eeSXin Li <DIV> 402*8c35d5eeSXin Li <xsl:attribute name="class"><xsl:value-of select="@class"/></xsl:attribute> 403*8c35d5eeSXin Li <PRE class="badcode"><xsl:call-template name="print_python_code"> 404*8c35d5eeSXin Li <xsl:with-param name="text" select="."/> 405*8c35d5eeSXin Li </xsl:call-template></PRE> 406*8c35d5eeSXin Li </DIV> 407*8c35d5eeSXin Li </xsl:template> 408*8c35d5eeSXin Li 409*8c35d5eeSXin Li <xsl:template match="FUNCTION"> 410*8c35d5eeSXin Li <xsl:call-template name="print_function_name"> 411*8c35d5eeSXin Li <xsl:with-param name="text" select="."/> 412*8c35d5eeSXin Li </xsl:call-template> 413*8c35d5eeSXin Li </xsl:template> 414*8c35d5eeSXin Li 415*8c35d5eeSXin Li <xsl:template match="SYNTAX"> 416*8c35d5eeSXin Li <I> 417*8c35d5eeSXin Li <xsl:attribute name="class"><xsl:value-of select="@class"/></xsl:attribute> 418*8c35d5eeSXin Li <xsl:apply-templates/> 419*8c35d5eeSXin Li </I> 420*8c35d5eeSXin Li </xsl:template> 421*8c35d5eeSXin Li 422*8c35d5eeSXin Li 423*8c35d5eeSXin Li <!-- This passes through any HTML elements that the 424*8c35d5eeSXin Li XML doc uses for minor formatting --> 425*8c35d5eeSXin Li <xsl:template match="a|address|blockquote|br|center|cite|code|dd|div|dl|dt|em|hr|i|img|li|ol|p|pre|span|table|td|th|tr|ul|var|A|ADDRESS|BLOCKQUOTE|BR|CENTER|CITE|CODE|DD|DIV|DL|DT|EM|HR|I|LI|OL|P|PRE|SPAN|TABLE|TD|TH|TR|UL|VAR"> 426*8c35d5eeSXin Li <xsl:element name="{local-name()}"> 427*8c35d5eeSXin Li <xsl:copy-of select="@*"/> 428*8c35d5eeSXin Li <xsl:apply-templates/> 429*8c35d5eeSXin Li </xsl:element> 430*8c35d5eeSXin Li </xsl:template> 431*8c35d5eeSXin Li 432*8c35d5eeSXin Li <!-- Builds the table of contents --> 433*8c35d5eeSXin Li <xsl:template name="TOC"> 434*8c35d5eeSXin Li <xsl:param name="root"/> 435*8c35d5eeSXin Li <DIV class="toc"> 436*8c35d5eeSXin Li <DIV class="toc_title">Table of Contents</DIV> 437*8c35d5eeSXin Li <TABLE> 438*8c35d5eeSXin Li <xsl:for-each select="$root/CATEGORY"> 439*8c35d5eeSXin Li <TR valign="top"> 440*8c35d5eeSXin Li <xsl:attribute name="class"><xsl:value-of select="@class"/></xsl:attribute> 441*8c35d5eeSXin Li <TD> 442*8c35d5eeSXin Li <DIV class="toc_category"> 443*8c35d5eeSXin Li <A> 444*8c35d5eeSXin Li <xsl:attribute name="href"> 445*8c35d5eeSXin Li <xsl:text>#</xsl:text> 446*8c35d5eeSXin Li <xsl:call-template name="anchorname"> 447*8c35d5eeSXin Li <xsl:with-param name="sectionname" select="@title"/> 448*8c35d5eeSXin Li </xsl:call-template> 449*8c35d5eeSXin Li </xsl:attribute> 450*8c35d5eeSXin Li <xsl:value-of select="@title"/> 451*8c35d5eeSXin Li </A> 452*8c35d5eeSXin Li </DIV> 453*8c35d5eeSXin Li </TD><TD> 454*8c35d5eeSXin Li <DIV class="toc_stylepoint"> 455*8c35d5eeSXin Li <xsl:for-each select="./STYLEPOINT"> 456*8c35d5eeSXin Li <SPAN style="padding-right: 1em; white-space:nowrap;"> 457*8c35d5eeSXin Li <xsl:attribute name="class"><xsl:value-of select="@class"/></xsl:attribute> 458*8c35d5eeSXin Li <A> 459*8c35d5eeSXin Li <xsl:attribute name="href"> 460*8c35d5eeSXin Li <xsl:text>#</xsl:text> 461*8c35d5eeSXin Li <xsl:call-template name="anchorname"> 462*8c35d5eeSXin Li <xsl:with-param name="sectionname" select="@title"/> 463*8c35d5eeSXin Li </xsl:call-template> 464*8c35d5eeSXin Li </xsl:attribute> 465*8c35d5eeSXin Li <xsl:value-of select="@title"/> 466*8c35d5eeSXin Li </A> 467*8c35d5eeSXin Li </SPAN> 468*8c35d5eeSXin Li <xsl:text> </xsl:text> 469*8c35d5eeSXin Li </xsl:for-each> 470*8c35d5eeSXin Li </DIV> 471*8c35d5eeSXin Li </TD> 472*8c35d5eeSXin Li </TR> 473*8c35d5eeSXin Li </xsl:for-each> 474*8c35d5eeSXin Li </TABLE> 475*8c35d5eeSXin Li </DIV> 476*8c35d5eeSXin Li </xsl:template> 477*8c35d5eeSXin Li 478*8c35d5eeSXin Li <xsl:template name="TOC_one_stylepoint"> 479*8c35d5eeSXin Li <xsl:param name="stylepoint"/> 480*8c35d5eeSXin Li </xsl:template> 481*8c35d5eeSXin Li 482*8c35d5eeSXin Li <!-- Creates a standard anchor given any text. 483*8c35d5eeSXin Li Substitutes underscore for characters unsuitable for URLs --> 484*8c35d5eeSXin Li <xsl:template name="anchorname"> 485*8c35d5eeSXin Li <xsl:param name="sectionname"/> 486*8c35d5eeSXin Li <!-- strange quoting necessary to strip apostrophes --> 487*8c35d5eeSXin Li <xsl:variable name="bad_characters" select="" ()#'""/> 488*8c35d5eeSXin Li <xsl:value-of select="translate($sectionname,$bad_characters,'_____')"/> 489*8c35d5eeSXin Li </xsl:template> 490*8c35d5eeSXin Li 491*8c35d5eeSXin Li <!-- Given text, evaluates to the number of leading spaces. --> 492*8c35d5eeSXin Li <!-- TODO(csilvers): deal well with leading tabs (treat as 8 spaces?) --> 493*8c35d5eeSXin Li <xsl:template name="num_leading_spaces_one_line"> 494*8c35d5eeSXin Li <xsl:param name="text"/> 495*8c35d5eeSXin Li <xsl:param name="current_count"/> 496*8c35d5eeSXin Li <xsl:choose> 497*8c35d5eeSXin Li <xsl:when test="starts-with($text, ' ')"> 498*8c35d5eeSXin Li <xsl:call-template name="num_leading_spaces_one_line"> 499*8c35d5eeSXin Li <xsl:with-param name="text" select="substring($text, 2)"/> 500*8c35d5eeSXin Li <xsl:with-param name="current_count" select="$current_count + 1"/> 501*8c35d5eeSXin Li </xsl:call-template> 502*8c35d5eeSXin Li </xsl:when> 503*8c35d5eeSXin Li <xsl:otherwise> 504*8c35d5eeSXin Li <xsl:value-of select="$current_count"/> 505*8c35d5eeSXin Li </xsl:otherwise> 506*8c35d5eeSXin Li </xsl:choose> 507*8c35d5eeSXin Li </xsl:template> 508*8c35d5eeSXin Li 509*8c35d5eeSXin Li <!-- Given a block of text, each line terminated by \n, evaluates to 510*8c35d5eeSXin Li the indentation-level of that text; that is, the largest number 511*8c35d5eeSXin Li n such that every non-blank line starts with at least n spaces. --> 512*8c35d5eeSXin Li <xsl:template name="num_leading_spaces"> 513*8c35d5eeSXin Li <xsl:param name="text"/> 514*8c35d5eeSXin Li <xsl:param name="max_so_far"/> 515*8c35d5eeSXin Li <!-- TODO(csilvers): deal with case text doesn't end in a newline --> 516*8c35d5eeSXin Li <xsl:variable name="line" select="substring-before($text, '
')"/> 517*8c35d5eeSXin Li <xsl:variable name="rest" select="substring-after($text, '
')"/> 518*8c35d5eeSXin Li <xsl:variable name="num_spaces_this_line"> 519*8c35d5eeSXin Li <xsl:choose> 520*8c35d5eeSXin Li <xsl:when test="$line=''"> 521*8c35d5eeSXin Li <xsl:value-of select="$max_so_far"/> 522*8c35d5eeSXin Li </xsl:when> 523*8c35d5eeSXin Li <xsl:otherwise> 524*8c35d5eeSXin Li <xsl:call-template name="num_leading_spaces_one_line"> 525*8c35d5eeSXin Li <xsl:with-param name="text" select="$line"/> 526*8c35d5eeSXin Li <xsl:with-param name="current_count" select="0"/> 527*8c35d5eeSXin Li </xsl:call-template> 528*8c35d5eeSXin Li </xsl:otherwise> 529*8c35d5eeSXin Li </xsl:choose> 530*8c35d5eeSXin Li </xsl:variable> 531*8c35d5eeSXin Li <xsl:variable name="new_max_so_far"> 532*8c35d5eeSXin Li <xsl:choose> 533*8c35d5eeSXin Li <xsl:when test="$num_spaces_this_line < $max_so_far"> 534*8c35d5eeSXin Li <xsl:value-of select="$num_spaces_this_line"/> 535*8c35d5eeSXin Li </xsl:when> 536*8c35d5eeSXin Li <xsl:otherwise> 537*8c35d5eeSXin Li <xsl:value-of select="$max_so_far"/> 538*8c35d5eeSXin Li </xsl:otherwise> 539*8c35d5eeSXin Li </xsl:choose> 540*8c35d5eeSXin Li </xsl:variable> 541*8c35d5eeSXin Li <!-- now check if we're on the last line, and if not, recurse --> 542*8c35d5eeSXin Li <xsl:if test="$rest=''"> 543*8c35d5eeSXin Li <xsl:value-of select="$new_max_so_far"/> 544*8c35d5eeSXin Li </xsl:if> 545*8c35d5eeSXin Li <xsl:if test="not($rest='')"> 546*8c35d5eeSXin Li <xsl:call-template name="num_leading_spaces"> 547*8c35d5eeSXin Li <xsl:with-param name="text" select="$rest"/> 548*8c35d5eeSXin Li <xsl:with-param name="max_so_far" select="$new_max_so_far"/> 549*8c35d5eeSXin Li </xsl:call-template> 550*8c35d5eeSXin Li </xsl:if> 551*8c35d5eeSXin Li </xsl:template> 552*8c35d5eeSXin Li 553*8c35d5eeSXin Li <!-- Given text, determine the starting position of code. 554*8c35d5eeSXin Li This similar to num_leading_spaces_one_line but treats "Yes:" and "No:" 555*8c35d5eeSXin Li as spaces. Also, if there is no code on the first line, it searches 556*8c35d5eeSXin Li subsequent lines until a non-empty line is found. 557*8c35d5eeSXin Li Used to find the start of code in snippets like: 558*8c35d5eeSXin Li Yes: if(foo): 559*8c35d5eeSXin Li No : if(foo): 560*8c35d5eeSXin Li As well as: 561*8c35d5eeSXin Li Yes: 562*8c35d5eeSXin Li if (foo): 563*8c35d5eeSXin Li --> 564*8c35d5eeSXin Li <xsl:template name="code_start_index"> 565*8c35d5eeSXin Li <xsl:param name="text"/> 566*8c35d5eeSXin Li <xsl:param name="current_count"/> 567*8c35d5eeSXin Li <xsl:choose> 568*8c35d5eeSXin Li <xsl:when test="starts-with($text, ' ')"> 569*8c35d5eeSXin Li <xsl:call-template name="code_start_index"> 570*8c35d5eeSXin Li <xsl:with-param name="text" select="substring($text, 2)"/> 571*8c35d5eeSXin Li <xsl:with-param name="current_count" select="$current_count + 1"/> 572*8c35d5eeSXin Li </xsl:call-template> 573*8c35d5eeSXin Li </xsl:when> 574*8c35d5eeSXin Li <xsl:when test="starts-with($text, 'Yes:')"> 575*8c35d5eeSXin Li <xsl:call-template name="code_start_index"> 576*8c35d5eeSXin Li <xsl:with-param name="text" select="substring($text, 5)"/> 577*8c35d5eeSXin Li <xsl:with-param name="current_count" select="$current_count + 4"/> 578*8c35d5eeSXin Li </xsl:call-template> 579*8c35d5eeSXin Li </xsl:when> 580*8c35d5eeSXin Li <xsl:when test="starts-with($text, 'No:')"> 581*8c35d5eeSXin Li <xsl:call-template name="code_start_index"> 582*8c35d5eeSXin Li <xsl:with-param name="text" select="substring($text, 4)"/> 583*8c35d5eeSXin Li <xsl:with-param name="current_count" select="$current_count + 3"/> 584*8c35d5eeSXin Li </xsl:call-template> 585*8c35d5eeSXin Li </xsl:when> 586*8c35d5eeSXin Li <!-- This is only reached if the first line is entirely whitespace or 587*8c35d5eeSXin Li contains nothing but "Yes:" or "No:"--> 588*8c35d5eeSXin Li <xsl:when test="starts-with($text, '
')"> 589*8c35d5eeSXin Li <xsl:call-template name="code_start_index"> 590*8c35d5eeSXin Li <xsl:with-param name="text" select="substring($text, 2)"/> 591*8c35d5eeSXin Li <xsl:with-param name="current_count" select="0"/> 592*8c35d5eeSXin Li </xsl:call-template> 593*8c35d5eeSXin Li </xsl:when> 594*8c35d5eeSXin Li <xsl:otherwise> 595*8c35d5eeSXin Li <xsl:value-of select="$current_count"/> 596*8c35d5eeSXin Li </xsl:otherwise> 597*8c35d5eeSXin Li </xsl:choose> 598*8c35d5eeSXin Li </xsl:template> 599*8c35d5eeSXin Li 600*8c35d5eeSXin Li <!-- Helper for ends_with_colon. Determine whether the given line is nothing 601*8c35d5eeSXin Li but spaces and python-style comments. --> 602*8c35d5eeSXin Li <xsl:template name="is_blank_or_comment"> 603*8c35d5eeSXin Li <xsl:param name="line"/> 604*8c35d5eeSXin Li <xsl:choose> 605*8c35d5eeSXin Li <xsl:when test="$line = ''"> 606*8c35d5eeSXin Li <xsl:value-of select="1"/> 607*8c35d5eeSXin Li </xsl:when> 608*8c35d5eeSXin Li <xsl:when test="starts-with($line, '
')"> 609*8c35d5eeSXin Li <xsl:value-of select="1"/> 610*8c35d5eeSXin Li </xsl:when> 611*8c35d5eeSXin Li <xsl:when test="starts-with($line, '#')"> 612*8c35d5eeSXin Li <xsl:value-of select="1"/> 613*8c35d5eeSXin Li </xsl:when> 614*8c35d5eeSXin Li <xsl:when test="starts-with($line, ' ')"> 615*8c35d5eeSXin Li <xsl:call-template name="is_blank_or_comment"> 616*8c35d5eeSXin Li <xsl:with-param name="line" select="substring($line, 2)"/> 617*8c35d5eeSXin Li </xsl:call-template> 618*8c35d5eeSXin Li </xsl:when> 619*8c35d5eeSXin Li <xsl:otherwise> 620*8c35d5eeSXin Li <xsl:value-of select="0"/> 621*8c35d5eeSXin Li </xsl:otherwise> 622*8c35d5eeSXin Li </xsl:choose> 623*8c35d5eeSXin Li </xsl:template> 624*8c35d5eeSXin Li 625*8c35d5eeSXin Li <!-- Determine whether the given line ends with a colon. Note that Python 626*8c35d5eeSXin Li style comments are ignored so the following lines return True: 627*8c35d5eeSXin Li - def foo(): 628*8c35d5eeSXin Li - def foo(): # Bar 629*8c35d5eeSXin Li - if(foo): 630*8c35d5eeSXin Li 631*8c35d5eeSXin Li But some code may confuse this function. For example the following are 632*8c35d5eeSXin Li also consider to "end_with_colon" even though they don't for Python 633*8c35d5eeSXin Li - foo(": #") 634*8c35d5eeSXin Li - foo() # No need for : 635*8c35d5eeSXin Li --> 636*8c35d5eeSXin Li <xsl:template name="ends_with_colon"> 637*8c35d5eeSXin Li <xsl:param name="line"/> 638*8c35d5eeSXin Li <xsl:param name="found_colon"/> 639*8c35d5eeSXin Li <xsl:choose> 640*8c35d5eeSXin Li <xsl:when test="$line = ''"> 641*8c35d5eeSXin Li <xsl:value-of select="$found_colon"/> 642*8c35d5eeSXin Li </xsl:when> 643*8c35d5eeSXin Li <xsl:when test="starts-with($line, '
')"> 644*8c35d5eeSXin Li <xsl:value-of select="$found_colon"/> 645*8c35d5eeSXin Li </xsl:when> 646*8c35d5eeSXin Li <xsl:when test="starts-with($line, ' ')"> 647*8c35d5eeSXin Li <xsl:call-template name="ends_with_colon"> 648*8c35d5eeSXin Li <xsl:with-param name="line" select="substring($line, 2)"/> 649*8c35d5eeSXin Li <xsl:with-param name="found_colon" select="$found_colon"/> 650*8c35d5eeSXin Li </xsl:call-template> 651*8c35d5eeSXin Li </xsl:when> 652*8c35d5eeSXin Li <xsl:when test="starts-with($line, ':')"> 653*8c35d5eeSXin Li <xsl:variable name="rest_is_comment"> 654*8c35d5eeSXin Li <xsl:call-template name="is_blank_or_comment"> 655*8c35d5eeSXin Li <xsl:with-param name="line" select="substring($line, 2)"/> 656*8c35d5eeSXin Li </xsl:call-template> 657*8c35d5eeSXin Li </xsl:variable> 658*8c35d5eeSXin Li <xsl:choose> 659*8c35d5eeSXin Li <xsl:when test="$rest_is_comment = '1'"> 660*8c35d5eeSXin Li <xsl:value-of select="1"/> 661*8c35d5eeSXin Li </xsl:when> 662*8c35d5eeSXin Li <xsl:otherwise> 663*8c35d5eeSXin Li <xsl:call-template name="ends_with_colon"> 664*8c35d5eeSXin Li <xsl:with-param name="line" select="substring($line, 2)"/> 665*8c35d5eeSXin Li <xsl:with-param name="found_colon" select="0"/> 666*8c35d5eeSXin Li </xsl:call-template> 667*8c35d5eeSXin Li </xsl:otherwise> 668*8c35d5eeSXin Li </xsl:choose> 669*8c35d5eeSXin Li </xsl:when> 670*8c35d5eeSXin Li <xsl:otherwise> 671*8c35d5eeSXin Li <xsl:call-template name="ends_with_colon"> 672*8c35d5eeSXin Li <xsl:with-param name="line" select="substring($line, 2)"/> 673*8c35d5eeSXin Li <xsl:with-param name="found_colon" select="0"/> 674*8c35d5eeSXin Li </xsl:call-template> 675*8c35d5eeSXin Li </xsl:otherwise> 676*8c35d5eeSXin Li </xsl:choose> 677*8c35d5eeSXin Li </xsl:template> 678*8c35d5eeSXin Li 679*8c35d5eeSXin Li <!-- Prints one line of python code with proper indent and calls itself 680*8c35d5eeSXin Li recursively for the rest of the text. 681*8c35d5eeSXin Li This template uses "a", "b", "c" and "d" to refer to four key column 682*8c35d5eeSXin Li numbers. They are: 683*8c35d5eeSXin Li - a: the indentation common to all lines in a code snippet. This is 684*8c35d5eeSXin Li stripped out to allow for cleaner code in the xml. 685*8c35d5eeSXin Li - b: the indentation of the most out-dented line of code. This is 686*8c35d5eeSXin Li different from "a" when code is labelled with "Yes:" or "No:" 687*8c35d5eeSXin Li - c: the indentation of the current python block, in other words, the 688*8c35d5eeSXin Li indentation of the first line of this block, which is the 689*8c35d5eeSXin Li indentation of the last line we saw that ended with a colon. 690*8c35d5eeSXin Li - d: the "total" indentation of the line, ignorng possible "Yes:" or 691*8c35d5eeSXin Li "No:" text on the line. 692*8c35d5eeSXin Li 693*8c35d5eeSXin Li For example, for the last line of the following code snippet, the 694*8c35d5eeSXin Li positions of a, b, c and d are indicated below: 695*8c35d5eeSXin Li Yes: def Foo(): 696*8c35d5eeSXin Li if bar(): 697*8c35d5eeSXin Li a += 1 698*8c35d5eeSXin Li baz() 699*8c35d5eeSXin Li a b c d 700*8c35d5eeSXin Li 701*8c35d5eeSXin Li The algorithm is: 702*8c35d5eeSXin Li 1) Split the text into first line and the rest. Note that the 703*8c35d5eeSXin Li substring-before function is supposed to handle the case where the 704*8c35d5eeSXin Li character is not present in the string but does not so we 705*8c35d5eeSXin Li automatically ignore the last line of the snippet which is always 706*8c35d5eeSXin Li empty (the closing snippet tag). This is consistent with the 707*8c35d5eeSXin Li behavior or print_without_leading_chars. 708*8c35d5eeSXin Li 2) If the current is empty (only whitespace), print newline and call 709*8c35d5eeSXin Li itself recursively on the rest of the text with the rest of the 710*8c35d5eeSXin Li parameters unchanged. 711*8c35d5eeSXin Li 3) Otherwise, measure "d" 712*8c35d5eeSXin Li 4) Measure "c" by taking: 713*8c35d5eeSXin Li - the value of "d" if the previous line ended with a colon or the 714*8c35d5eeSXin Li current line is outdented compare to the previous line 715*8c35d5eeSXin Li - the indent of the previous line otherwise 716*8c35d5eeSXin Li 5) Print line[a:c] (Note that we ignore line[0:a]) 717*8c35d5eeSXin Li 6) Print line[b:c] in an external span (in order to double the block 718*8c35d5eeSXin Li indent in external code). 719*8c35d5eeSXin Li 7) Print line[c:<end>] with function names processed to produce both 720*8c35d5eeSXin Li internal and external names. 721*8c35d5eeSXin Li 8) If there are more lines, recurse. 722*8c35d5eeSXin Li --> 723*8c35d5eeSXin Li <xsl:template name="print_python_line_recursively"> 724*8c35d5eeSXin Li <xsl:param name="text"/> 725*8c35d5eeSXin Li <xsl:param name="a"/> 726*8c35d5eeSXin Li <xsl:param name="b"/> 727*8c35d5eeSXin Li <xsl:param name="previous_indent"/> 728*8c35d5eeSXin Li <xsl:param name="previous_ends_with_colon"/> 729*8c35d5eeSXin Li <xsl:param name="is_first_line"/> 730*8c35d5eeSXin Li <xsl:variable name="line" select="substring-before($text, '
')"/> 731*8c35d5eeSXin Li <xsl:variable name="rest" select="substring-after($text, '
')"/> 732*8c35d5eeSXin Li <xsl:choose> 733*8c35d5eeSXin Li <xsl:when test="substring($line, $b) = '' and not($rest = '')"> 734*8c35d5eeSXin Li <xsl:if test="not($is_first_line = '1')"> 735*8c35d5eeSXin Li <xsl:text>
</xsl:text> 736*8c35d5eeSXin Li </xsl:if> 737*8c35d5eeSXin Li <xsl:call-template name="print_python_line_recursively"> 738*8c35d5eeSXin Li <xsl:with-param name="text" select="$rest"/> 739*8c35d5eeSXin Li <xsl:with-param name="a" select="$a"/> 740*8c35d5eeSXin Li <xsl:with-param name="b" select="$b"/> 741*8c35d5eeSXin Li <xsl:with-param name="previous_indent" select="$previous_indent"/> 742*8c35d5eeSXin Li <xsl:with-param name="previous_ends_with_colon" 743*8c35d5eeSXin Li select="$previous_ends_with_colon"/> 744*8c35d5eeSXin Li <xsl:with-param name="is_first_line" select="0"/> 745*8c35d5eeSXin Li </xsl:call-template> 746*8c35d5eeSXin Li </xsl:when> 747*8c35d5eeSXin Li <xsl:otherwise> 748*8c35d5eeSXin Li <xsl:variable name="indent_after_b"> 749*8c35d5eeSXin Li <xsl:call-template name="num_leading_spaces_one_line"> 750*8c35d5eeSXin Li <xsl:with-param name="text" select="substring($line, $b + 1)"/> 751*8c35d5eeSXin Li <xsl:with-param name="current_count" select="0"/> 752*8c35d5eeSXin Li </xsl:call-template> 753*8c35d5eeSXin Li </xsl:variable> 754*8c35d5eeSXin Li <xsl:variable name="d" select="$b + $indent_after_b"/> 755*8c35d5eeSXin Li <xsl:variable name="c"> 756*8c35d5eeSXin Li <xsl:choose> 757*8c35d5eeSXin Li <xsl:when test="$previous_ends_with_colon = '1' or 758*8c35d5eeSXin Li $previous_indent > $d"> 759*8c35d5eeSXin Li <xsl:value-of select="$d"/> 760*8c35d5eeSXin Li </xsl:when> 761*8c35d5eeSXin Li <xsl:otherwise> 762*8c35d5eeSXin Li <xsl:value-of select="$previous_indent"/> 763*8c35d5eeSXin Li </xsl:otherwise> 764*8c35d5eeSXin Li </xsl:choose> 765*8c35d5eeSXin Li </xsl:variable> 766*8c35d5eeSXin Li 767*8c35d5eeSXin Li <xsl:value-of select="substring($line, $a + 1, $c - $a)"/> 768*8c35d5eeSXin Li <span class="external"> 769*8c35d5eeSXin Li <xsl:value-of select="substring($line, $b + 1, $c - $b)"/> 770*8c35d5eeSXin Li </span> 771*8c35d5eeSXin Li <xsl:call-template name="munge_function_names_in_text"> 772*8c35d5eeSXin Li <xsl:with-param name="stripped_line" 773*8c35d5eeSXin Li select="substring($line, $c + 1)"/> 774*8c35d5eeSXin Li </xsl:call-template> 775*8c35d5eeSXin Li <xsl:if test="not(substring($rest, $a) = '')"> 776*8c35d5eeSXin Li <xsl:text>
</xsl:text> 777*8c35d5eeSXin Li <xsl:call-template name="print_python_line_recursively"> 778*8c35d5eeSXin Li <xsl:with-param name="text" select="$rest"/> 779*8c35d5eeSXin Li <xsl:with-param name="a" select="$a"/> 780*8c35d5eeSXin Li <xsl:with-param name="b" select="$b"/> 781*8c35d5eeSXin Li <xsl:with-param name="previous_indent" select="$c"/> 782*8c35d5eeSXin Li <xsl:with-param name="previous_ends_with_colon"> 783*8c35d5eeSXin Li <xsl:call-template name="ends_with_colon"> 784*8c35d5eeSXin Li <xsl:with-param name="line" select="$line"/> 785*8c35d5eeSXin Li <xsl:with-param name="found_colon" select="0"/> 786*8c35d5eeSXin Li </xsl:call-template> 787*8c35d5eeSXin Li </xsl:with-param> 788*8c35d5eeSXin Li <xsl:with-param name="is_first_line" select="0"/> 789*8c35d5eeSXin Li </xsl:call-template> 790*8c35d5eeSXin Li </xsl:if> 791*8c35d5eeSXin Li </xsl:otherwise> 792*8c35d5eeSXin Li </xsl:choose> 793*8c35d5eeSXin Li </xsl:template> 794*8c35d5eeSXin Li 795*8c35d5eeSXin Li <!-- Print python code with internal and external styles. 796*8c35d5eeSXin Li In order to conform with PEP-8 externally, we identify 2-space indents 797*8c35d5eeSXin Li and an external-only 4-space indent. 798*8c35d5eeSXin Li Function names that are marked with $$FunctionName/$$ have an external 799*8c35d5eeSXin Li lower_with_underscore version added. --> 800*8c35d5eeSXin Li <xsl:template name="print_python_code"> 801*8c35d5eeSXin Li <xsl:param name="text"/> 802*8c35d5eeSXin Li 803*8c35d5eeSXin Li <xsl:variable name="a"> 804*8c35d5eeSXin Li <xsl:call-template name="num_leading_spaces"> 805*8c35d5eeSXin Li <xsl:with-param name="text" select="."/> 806*8c35d5eeSXin Li <xsl:with-param name="max_so_far" select="1000"/> 807*8c35d5eeSXin Li </xsl:call-template> 808*8c35d5eeSXin Li </xsl:variable> 809*8c35d5eeSXin Li 810*8c35d5eeSXin Li <xsl:variable name="b"> 811*8c35d5eeSXin Li <xsl:call-template name="code_start_index"> 812*8c35d5eeSXin Li <xsl:with-param name="text" select="$text"/> 813*8c35d5eeSXin Li <xsl:with-param name="current_count" select="0"/> 814*8c35d5eeSXin Li </xsl:call-template> 815*8c35d5eeSXin Li </xsl:variable> 816*8c35d5eeSXin Li 817*8c35d5eeSXin Li <xsl:call-template name="print_python_line_recursively"> 818*8c35d5eeSXin Li <xsl:with-param name="text" select="$text"/> 819*8c35d5eeSXin Li <xsl:with-param name="a" select="$a"/> 820*8c35d5eeSXin Li <xsl:with-param name="b" select="$b"/> 821*8c35d5eeSXin Li <xsl:with-param name="previous_indent" select="$b"/> 822*8c35d5eeSXin Li <xsl:with-param name="previous_ends_with_colon" select="0"/> 823*8c35d5eeSXin Li <xsl:with-param name="is_first_line" select="1"/> 824*8c35d5eeSXin Li </xsl:call-template> 825*8c35d5eeSXin Li </xsl:template> 826*8c35d5eeSXin Li 827*8c35d5eeSXin Li <!-- Given a block of text, each line terminated by \n, and a number n, 828*8c35d5eeSXin Li emits the text with the first n characters of each line 829*8c35d5eeSXin Li deleted. If strip==1, then we omit blank lines at the beginning 830*8c35d5eeSXin Li and end of the text (but not the middle!) --> 831*8c35d5eeSXin Li <!-- TODO(csilvers): deal well with leading tabs (treat as 8 spaces?) --> 832*8c35d5eeSXin Li <xsl:template name="print_without_leading_chars"> 833*8c35d5eeSXin Li <xsl:param name="text"/> 834*8c35d5eeSXin Li <xsl:param name="trim_count"/> 835*8c35d5eeSXin Li <xsl:param name="strip"/> 836*8c35d5eeSXin Li <xsl:param name="is_firstline"/> 837*8c35d5eeSXin Li <!-- TODO(csilvers): deal with case text doesn't end in a newline --> 838*8c35d5eeSXin Li <xsl:variable name="line" select="substring-before($text, '
')"/> 839*8c35d5eeSXin Li <xsl:variable name="rest" select="substring-after($text, '
')"/> 840*8c35d5eeSXin Li <xsl:variable name="stripped_line" select="substring($line, $trim_count+1)"/> 841*8c35d5eeSXin Li <xsl:choose> 842*8c35d5eeSXin Li <!-- $line (or $rest) is considered empty if we'd trim the entire line --> 843*8c35d5eeSXin Li <xsl:when test="($strip = '1') and ($is_firstline = '1') and 844*8c35d5eeSXin Li (string-length($line) <= $trim_count)"> 845*8c35d5eeSXin Li </xsl:when> 846*8c35d5eeSXin Li <xsl:when test="($strip = '1') and 847*8c35d5eeSXin Li (string-length($rest) <= $trim_count)"> 848*8c35d5eeSXin Li <xsl:value-of select="$stripped_line"/> 849*8c35d5eeSXin Li </xsl:when> 850*8c35d5eeSXin Li <xsl:otherwise> 851*8c35d5eeSXin Li <xsl:value-of select="$stripped_line"/> 852*8c35d5eeSXin Li <xsl:text>
</xsl:text> 853*8c35d5eeSXin Li </xsl:otherwise> 854*8c35d5eeSXin Li </xsl:choose> 855*8c35d5eeSXin Li <xsl:if test="not($rest='')"> 856*8c35d5eeSXin Li <xsl:call-template name="print_without_leading_chars"> 857*8c35d5eeSXin Li <xsl:with-param name="text" select="$rest"/> 858*8c35d5eeSXin Li <xsl:with-param name="trim_count" select="$trim_count"/> 859*8c35d5eeSXin Li <xsl:with-param name="strip" select="$strip"/> 860*8c35d5eeSXin Li <xsl:with-param name="is_firstline" select="0"/> 861*8c35d5eeSXin Li </xsl:call-template> 862*8c35d5eeSXin Li </xsl:if> 863*8c35d5eeSXin Li </xsl:template> 864*8c35d5eeSXin Li 865*8c35d5eeSXin Li <!-- Given a line of code, find function names that are marked with $$ /$$ and 866*8c35d5eeSXin Li print out the line with the internal and external versions of the 867*8c35d5eeSXin Li function names.--> 868*8c35d5eeSXin Li <xsl:template name="munge_function_names_in_text"> 869*8c35d5eeSXin Li <xsl:param name="stripped_line"/> 870*8c35d5eeSXin Li <xsl:choose> 871*8c35d5eeSXin Li <xsl:when test="contains($stripped_line, '$$')"> 872*8c35d5eeSXin Li <xsl:value-of select="substring-before($stripped_line, '$$')"/> 873*8c35d5eeSXin Li <xsl:call-template name="print_function_name"> 874*8c35d5eeSXin Li <xsl:with-param name="text" select="substring-after(substring-before($stripped_line, '/$$'), '$$')"/> 875*8c35d5eeSXin Li </xsl:call-template> 876*8c35d5eeSXin Li <xsl:call-template name="munge_function_names_in_text"> 877*8c35d5eeSXin Li <xsl:with-param name="stripped_line" select="substring-after($stripped_line, '/$$')"/> 878*8c35d5eeSXin Li </xsl:call-template> 879*8c35d5eeSXin Li </xsl:when> 880*8c35d5eeSXin Li <xsl:otherwise> 881*8c35d5eeSXin Li <xsl:value-of select="$stripped_line"/> 882*8c35d5eeSXin Li </xsl:otherwise> 883*8c35d5eeSXin Li </xsl:choose> 884*8c35d5eeSXin Li </xsl:template> 885*8c35d5eeSXin Li 886*8c35d5eeSXin Li <!-- Given a function name, print out both the internal and external version 887*8c35d5eeSXin Li of the function name in their respective spans.--> 888*8c35d5eeSXin Li <xsl:template name="print_function_name"> 889*8c35d5eeSXin Li <xsl:param name="text"/> 890*8c35d5eeSXin Li <xsl:call-template name="convert_camel_case_to_lowercase_with_under"> 891*8c35d5eeSXin Li <xsl:with-param name="text" select="$text"/> 892*8c35d5eeSXin Li </xsl:call-template> 893*8c35d5eeSXin Li </xsl:template> 894*8c35d5eeSXin Li 895*8c35d5eeSXin Li <!-- Given a single word of text convert it from CamelCase to 896*8c35d5eeSXin Li lower_with_under. 897*8c35d5eeSXin Li This means replacing each uppercase character with _ followed by the 898*8c35d5eeSXin Li lowercase version except for the first character which is replaced 899*8c35d5eeSXin Li without adding the _.--> 900*8c35d5eeSXin Li <xsl:template name="convert_camel_case_to_lowercase_with_under"> 901*8c35d5eeSXin Li <xsl:param name="text"/> 902*8c35d5eeSXin Li <xsl:param name="is_recursive_call"/> 903*8c35d5eeSXin Li <xsl:variable name="first_char" select="substring($text, 1, 1)"/> 904*8c35d5eeSXin Li <xsl:variable name="rest" select="substring($text, 2)"/> 905*8c35d5eeSXin Li <xsl:choose> 906*8c35d5eeSXin Li <xsl:when test="contains('ABCDEFGHIJKLMNOPQRSTUVWXYZ', $first_char)"> 907*8c35d5eeSXin Li <xsl:if test="$is_recursive_call='1'"> 908*8c35d5eeSXin Li <xsl:text>_</xsl:text> 909*8c35d5eeSXin Li </xsl:if> 910*8c35d5eeSXin Li <xsl:value-of select="translate($first_char, 'ABCDEFGHIJKLMNOPQRSTUVWXYZ', 'abcdefghijklmnopqrstuvwxyz')"/> 911*8c35d5eeSXin Li </xsl:when> 912*8c35d5eeSXin Li <xsl:otherwise> 913*8c35d5eeSXin Li <xsl:value-of select="$first_char" /> 914*8c35d5eeSXin Li </xsl:otherwise> 915*8c35d5eeSXin Li </xsl:choose> 916*8c35d5eeSXin Li <xsl:if test="not($rest='')"> 917*8c35d5eeSXin Li <xsl:call-template name="convert_camel_case_to_lowercase_with_under"> 918*8c35d5eeSXin Li <xsl:with-param name="text" select="$rest"/> 919*8c35d5eeSXin Li <xsl:with-param name="is_recursive_call" select="1"/> 920*8c35d5eeSXin Li </xsl:call-template> 921*8c35d5eeSXin Li </xsl:if> 922*8c35d5eeSXin Li </xsl:template> 923*8c35d5eeSXin Li</xsl:stylesheet> 924*8c35d5eeSXin Li 925