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