xref: /aosp_15_r20/external/google-styleguide/styleguide.xsl (revision 8c35d5ee8e2913d4bd6623e2b93232b1da0ab719)
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="'&#x25B6;'" />
13*8c35d5eeSXin Li  <xsl:variable name="hide_button_text" select="'&#x25BD;'" />
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 &amp;&amp; str.indexOf(suffix, l) == l;
109*8c35d5eeSXin Li                }
110*8c35d5eeSXin Li
111*8c35d5eeSXin Li                function RefreshVisibilityFromHashParam() {
112*8c35d5eeSXin Li                  var hashRegexp = new RegExp('#([^&amp;#]*)$');
113*8c35d5eeSXin Li                  var hashMatch = hashRegexp.exec(window.location.href);
114*8c35d5eeSXin Li                  var anchor = hashMatch &amp;&amp; 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 &amp;&amp; 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("[\\?&amp;](showall)=([^&amp;#]*)");
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("[\\?&amp;](showone)=([^&amp;#]*)");
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="&quot; ()#'&quot;"/>
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, '&#xA;')"/>
517*8c35d5eeSXin Li    <xsl:variable name="rest" select="substring-after($text, '&#xA;')"/>
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 &lt; $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, '&#xA;')">
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, '&#xA;')">
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, '&#xA;')">
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, '&#xA;')"/>
731*8c35d5eeSXin Li    <xsl:variable name="rest" select="substring-after($text, '&#xA;')"/>
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>&#xA;</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>&#xA;</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, '&#xA;')"/>
839*8c35d5eeSXin Li    <xsl:variable name="rest" select="substring-after($text, '&#xA;')"/>
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) &lt;= $trim_count)">
845*8c35d5eeSXin Li      </xsl:when>
846*8c35d5eeSXin Li      <xsl:when test="($strip = '1') and
847*8c35d5eeSXin Li                      (string-length($rest) &lt;= $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>&#xA;</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