]> git.draconx.ca Git - homepage.git/blob - layouts/creativecommons.xsl
Remove dead definition list cruft.
[homepage.git] / layouts / creativecommons.xsl
1 <?xml version='1.0' encoding='UTF-8' ?>
2 <!--
3   Nick's web site: Creative Commons license reformatter.
4
5   This tool processes the "official" Creative Commons license documents, some
6   of which come in a real messy SGML format, and converts them to usable XHTML.
7
8   Note that some of the source documents have tons of missing closing tags
9   so they will not parse correctly as XML.  The sgml2xml filter is intended to
10   fix this.
11
12   Copyright © 2018-2019 Nick Bowler
13
14   This program is free software: you can redistribute it and/or modify
15   it under the terms of the GNU General Public License as published by
16   the Free Software Foundation, either version 3 of the License, or
17   (at your option) any later version.
18
19   This program is distributed in the hope that it will be useful,
20   but WITHOUT ANY WARRANTY; without even the implied warranty of
21   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22   GNU General Public License for more details.
23
24   You should have received a copy of the GNU General Public License
25   along with this program.  If not, see <https://www.gnu.org/licenses/>
26 -->
27 <xsl:stylesheet version='1.0'
28   xmlns='http://www.w3.org/1999/xhtml'
29   xmlns:xhtml='http://www.w3.org/1999/xhtml'
30   xmlns:xsl='http://www.w3.org/1999/XSL/Transform'
31   xmlns:func='http://exslt.org/functions'
32   xmlns:f='http://draconx.ca/my-functions'
33   extension-element-prefixes='func f'
34   exclude-result-prefixes='xhtml'>
35
36 <xsl:strip-space elements='*' />
37 <xsl:output method='xml' encoding='UTF-8' omit-xml-declaration='yes' indent='yes' />
38
39 <xsl:template match='node()|@*'>
40   <xsl:copy><xsl:apply-templates select='node()|@*' /></xsl:copy>
41 </xsl:template>
42
43 <!-- identity rule to patch up namespace -->
44 <xsl:template name='fixup-node' match='*'>
45   <xsl:element name='{local-name(.)}' namespace='http://www.w3.org/1999/xhtml'>
46     <xsl:apply-templates select='node()|@*' />
47   </xsl:element>
48 </xsl:template>
49
50 <xsl:template match='node()'>
51   <xsl:param name='list-label' />
52
53   <xsl:if test='$list-label'>
54     <span><xsl:value-of select='$list-label' />&#xa0;</span>
55   </xsl:if>
56
57   <xsl:choose>
58     <xsl:when test='self::text()'>
59       <xsl:copy />
60     </xsl:when>
61     <xsl:otherwise>
62       <xsl:call-template name='fixup-node' />
63     </xsl:otherwise>
64   </xsl:choose>
65 </xsl:template>
66
67 <xsl:template match='p'>
68   <xsl:param name='list-label' />
69
70   <p>
71     <xsl:apply-templates select='@*' />
72     <xsl:if test='$list-label'>
73       <span><xsl:value-of select='$list-label' />&#xa0;</span>
74     </xsl:if>
75     <xsl:apply-templates select='node()' />
76   </p>
77 </xsl:template>
78
79 <xsl:template match='span[@style]'>
80   <xsl:param name='list-label' />
81
82   <xsl:if test='$list-label'>
83     <span><xsl:value-of select='$list-label' />&#xa0;</span>
84   </xsl:if>
85
86   <em><xsl:apply-templates select='node()' /></em>
87 </xsl:template>
88
89 <!-- Older XHTML editions have title in h2 outside of deed-main-content -->
90 <xsl:template mode='toplevel' match='xhtml:h2'>
91   <h1><xsl:apply-templates select='node()|@*' /></h1>
92 </xsl:template>
93
94 <xsl:template match='h3'>
95   <h1><xsl:apply-templates select='node()|@*' /></h1>
96 </xsl:template>
97
98 <xsl:template name='cc-section-heading'>
99   <xsl:param name='heading' select='strong[1]|xhtml:strong[1]' />
100   <xsl:choose>
101     <xsl:when test='substring($heading, string-length($heading))="."'>
102       <xsl:value-of
103         select='substring($heading, 1, string-length($heading)-1)' />
104     </xsl:when>
105     <xsl:otherwise>
106       <xsl:value-of select='$heading' />
107     </xsl:otherwise>
108   </xsl:choose>
109 </xsl:template>
110
111 <xsl:template match='p[starts-with(strong, "Section")]'>
112   <h2>
113     <xsl:apply-templates select='@*' />
114     <xsl:call-template name='cc-section-heading' />
115   </h2>
116 </xsl:template>
117
118 <xsl:template match='xhtml:h3[xhtml:em[1]]'>
119   <h2>
120     <xsl:value-of select='.' />
121   </h2>
122 </xsl:template>
123
124 <xsl:template match='xhtml:p[xhtml:strong[1]]'>
125   <xsl:variable name='heading' select='xhtml:strong[1]' />
126   <xsl:variable name='section-num'
127     select='number(substring-before($heading, "."))' />
128
129   <h2>
130     <xsl:if test='$section-num'>
131       <xsl:attribute name='id'>
132         <xsl:value-of select='concat("s", $section-num)' />
133       </xsl:attribute>
134     </xsl:if>
135     <xsl:call-template name='cc-section-heading' />
136   </h2>
137   <p>
138     <xsl:apply-templates select='@*|node()[position()>1]' />
139   </p>
140 </xsl:template>
141
142 <xsl:template match='a[normalize-space(text())=
143                        "creativecommons.org/compatiblelicenses"]'>
144   <a href='https://{normalize-space(text())}'>
145     <xsl:apply-templates select='@*[local-name(.)!="href"]' />
146     <xsl:text>https://&#x200b;</xsl:text>
147     <xsl:text>creative&#xad;commons.org/&#x200b;</xsl:text>
148     <xsl:text>compatible&#xad;licenses</xsl:text>
149   </a>
150 </xsl:template>
151
152 <xsl:template match='div'>
153   <xsl:apply-templates select='node()' />
154 </xsl:template>
155
156 <xsl:template name='list-number'>
157   <xsl:param name='type' select='substring(concat(../@type,"1"),1,1)' />
158   <xsl:param name='start' select='(text()[normalize-space(.)] | *)[1]' />
159   <xsl:param name='count' select='count(node())' />
160
161   <xsl:apply-templates select='$start'>
162     <xsl:with-param name='list-label'>
163       <xsl:number value='position()' format='{$type}.' />
164     </xsl:with-param>
165   </xsl:apply-templates>
166   <xsl:apply-templates
167     select='$start/following-sibling::node()[$count>position()]' />
168 </xsl:template>
169
170 <xsl:template match='ol/li|xhtml:ol/xhtml:li'>
171   <xsl:variable name='first' select='(text()[normalize-space(.)] | *)[1]' />
172   <xsl:variable name='firstblock' select='*[f:node-is-block(.)]' />
173
174   <li>
175     <xsl:apply-templates select='@*' />
176     <xsl:choose>
177       <xsl:when test='$first/self::p'>
178         <xsl:call-template name='list-number' />
179       </xsl:when>
180       <xsl:when test='$firstblock' xml:space='preserve'>
181         <p>
182           <xsl:call-template name='list-number' xml:space='default'>
183             <xsl:with-param name='count'
184               select='count($first/following-sibling::*[f:node-is-span(.)])+1' />
185           </xsl:call-template>
186         </p>
187         <xsl:apply-templates
188           select='$firstblock|$firstblock/following-sibling::node()' />
189       </xsl:when>
190       <xsl:otherwise xml:space='preserve'>
191         <p>
192           <xsl:call-template name='list-number' xml:space='default' />
193         </p>
194       </xsl:otherwise>
195     </xsl:choose>
196   </li>
197 </xsl:template>
198
199 <xsl:template match='ol|xhtml:ol'>
200   <xsl:variable name='type' select='@type' />
201
202   <ul class='ordered'>
203     <xsl:apply-templates select='li | xhtml:li
204         | following-sibling::*[1][self::ol and @start]/li' />
205   </ul>
206 </xsl:template>
207 <xsl:template match='ol[@start]' />
208
209 <xsl:template match='node()[following-sibling::h3]' />
210 <xsl:template match='node()[preceding-sibling::p[@class="shaded"]]' />
211 <xsl:template match='node()[@class="shaded"]' />
212 <xsl:template match='node()[following-sibling::xhtml:h3]' />
213 <xsl:template match='xhtml:blockquote' />
214
215 <xsl:template mode='toplevel' match='text()|@*' />
216 <xsl:template mode='toplevel' match='*[@id="deed-main-content"]/node()'>
217   <xsl:apply-templates select='.' />
218 </xsl:template>
219
220 <func:function name='f:node-is-block'>
221   <xsl:param name='node' select='.' />
222   <xsl:variable name='tag' select='local-name($node)' />
223
224   <!-- XXX incomplete -->
225   <func:result select='starts-with($tag, "h") or $tag="div" or $tag="p"
226                        or $tag="ul" or $tag="ol" or $tag="blockquote"' />
227 </func:function>
228
229 <func:function name='f:node-is-span'>
230   <xsl:param name='node' select='.' />
231
232   <xsl:choose>
233     <xsl:when test='$node/self::text()'>
234       <func:result select='normalize-space($node)' />
235     </xsl:when>
236     <xsl:otherwise>
237       <func:result select='not(f:node-is-block($node))' />
238     </xsl:otherwise>
239   </xsl:choose>
240 </func:function>
241
242 <func:function name='f:consecutive-spans'>
243   <xsl:param name='start' select='.' />
244   <xsl:param name='next' select='$start/following-sibling::node()[1]' />
245
246   <xsl:choose>
247     <xsl:when test='f:node-is-span($start)'>
248       <func:result select='$start | f:consecutive-spans($next)' />
249     </xsl:when>
250     <xsl:otherwise>
251       <func:result select='/..' />
252     </xsl:otherwise>
253   </xsl:choose>
254 </func:function>
255
256 <xsl:template mode='toplevel' match='*[@id="deed-main-content"]/node()[f:node-is-span(.)]'>
257   <xsl:variable name='prev' select='preceding-sibling::node()[1]' />
258
259   <xsl:if test='not(f:node-is-span($prev) or self::img)'>
260     <p>
261       <xsl:apply-templates select='f:consecutive-spans(.)' />
262     </p>
263   </xsl:if>
264 </xsl:template>
265
266 <xsl:template match='/'>
267   <xsl:apply-templates mode='toplevel' select='*' />
268 </xsl:template>
269
270 </xsl:stylesheet>