]> git.draconx.ca Git - homepage.git/blobdiff - layouts/creativecommons.xsl
Add copyright license information.
[homepage.git] / layouts / creativecommons.xsl
diff --git a/layouts/creativecommons.xsl b/layouts/creativecommons.xsl
new file mode 100644 (file)
index 0000000..89fadd4
--- /dev/null
@@ -0,0 +1,282 @@
+<?xml version='1.0' encoding='UTF-8' ?>
+<!--
+  Nick's web site: Creative Commons license reformatter.
+
+  This tool processes the "official" Creative Commons license documents, some
+  of which come in a real messy SGML format, and converts them to usable XHTML.
+
+  Note that some of the source documents have tons of missing closing tags
+  so they will not parse correctly as XML.  The sgml2xml filter is intended to
+  fix this.
+
+  Copyright © 2018 Nick Bowler
+
+  This program is free software: you can redistribute it and/or modify
+  it under the terms of the GNU General Public License as published by
+  the Free Software Foundation, either version 3 of the License, or
+  (at your option) any later version.
+
+  This program is distributed in the hope that it will be useful,
+  but WITHOUT ANY WARRANTY; without even the implied warranty of
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+  GNU General Public License for more details.
+
+  You should have received a copy of the GNU General Public License
+  along with this program.  If not, see <https://www.gnu.org/licenses/>
+-->
+<xsl:stylesheet version='1.0'
+  xmlns='http://www.w3.org/1999/xhtml'
+  xmlns:xhtml='http://www.w3.org/1999/xhtml'
+  xmlns:xsl='http://www.w3.org/1999/XSL/Transform'
+  xmlns:func='http://exslt.org/functions'
+  xmlns:f='http://draconx.ca/my-functions'
+  extension-element-prefixes='func f'
+  exclude-result-prefixes='xhtml'>
+
+<xsl:strip-space elements='*' />
+<xsl:output method='xml' encoding='UTF-8' omit-xml-declaration='yes' indent='yes' />
+
+<xsl:template match='node()|@*'>
+  <xsl:copy><xsl:apply-templates select='node()|@*' /></xsl:copy>
+</xsl:template>
+
+<!-- identity rule to patch up namespace -->
+<xsl:template name='fixup-node' match='*'>
+  <xsl:element name='{local-name(.)}' namespace='http://www.w3.org/1999/xhtml'>
+    <xsl:apply-templates select='node()|@*' />
+  </xsl:element>
+</xsl:template>
+
+<xsl:template match='node()'>
+  <xsl:param name='list-label' />
+
+  <xsl:if test='$list-label'>
+    <span><xsl:value-of select='$list-label' />&#xa0;</span>
+  </xsl:if>
+
+  <xsl:choose>
+    <xsl:when test='self::text()'>
+      <xsl:copy />
+    </xsl:when>
+    <xsl:otherwise>
+      <xsl:call-template name='fixup-node' />
+    </xsl:otherwise>
+  </xsl:choose>
+</xsl:template>
+
+<xsl:template match='p'>
+  <xsl:param name='list-label' />
+
+  <p>
+    <xsl:apply-templates select='@*' />
+    <xsl:if test='$list-label'>
+      <span><xsl:value-of select='$list-label' />&#xa0;</span>
+    </xsl:if>
+    <xsl:apply-templates select='node()' />
+  </p>
+</xsl:template>
+
+<xsl:template match='span[@style]'>
+  <xsl:param name='list-label' />
+
+  <xsl:if test='$list-label'>
+    <span><xsl:value-of select='$list-label' />&#xa0;</span>
+  </xsl:if>
+
+  <em><xsl:apply-templates select='node()' /></em>
+</xsl:template>
+
+<!-- Older XHTML editions have title in h2 outside of deed-main-content -->
+<xsl:template mode='toplevel' match='xhtml:h2'>
+  <h1><xsl:apply-templates select='node()|@*' /></h1>
+</xsl:template>
+
+<xsl:template match='h3'>
+  <h1><xsl:apply-templates select='node()|@*' /></h1>
+</xsl:template>
+
+<xsl:template name='cc-section-heading'>
+  <xsl:param name='heading' select='strong[1]|xhtml:strong[1]' />
+  <xsl:choose>
+    <xsl:when test='substring($heading, string-length($heading))="."'>
+      <xsl:value-of
+        select='substring($heading, 1, string-length($heading)-1)' />
+    </xsl:when>
+    <xsl:otherwise>
+      <xsl:value-of select='$heading' />
+    </xsl:otherwise>
+  </xsl:choose>
+</xsl:template>
+
+<xsl:template match='p[starts-with(strong, "Section")]'>
+  <h2>
+    <xsl:apply-templates select='@*' />
+    <xsl:call-template name='cc-section-heading' />
+  </h2>
+</xsl:template>
+
+<xsl:template match='xhtml:h3[xhtml:em[1]]'>
+  <h2>
+    <xsl:value-of select='.' />
+  </h2>
+</xsl:template>
+
+<xsl:template match='xhtml:p[xhtml:strong[1]]'>
+  <xsl:variable name='heading' select='xhtml:strong[1]' />
+  <xsl:variable name='section-num'
+    select='number(substring-before($heading, "."))' />
+
+  <h2>
+    <xsl:if test='$section-num'>
+      <xsl:attribute name='id'>
+        <xsl:value-of select='concat("s", $section-num)' />
+      </xsl:attribute>
+    </xsl:if>
+    <xsl:call-template name='cc-section-heading' />
+  </h2>
+  <p>
+    <xsl:apply-templates select='@*|node()[position()>1]' />
+  </p>
+</xsl:template>
+
+<xsl:template match='a[normalize-space(text())=
+                       "creativecommons.org/compatiblelicenses"]'>
+  <a href='https://{normalize-space(text())}'>
+    <xsl:apply-templates select='@*[local-name(.)!="href"]' />
+    <xsl:text>https://&#x200b;</xsl:text>
+    <xsl:text>creative&#xad;commons.org/&#x200b;</xsl:text>
+    <xsl:text>compatible&#xad;licenses</xsl:text>
+  </a>
+</xsl:template>
+
+<xsl:template match='div'>
+  <xsl:apply-templates select='node()' />
+</xsl:template>
+
+<xsl:template name='list-number'>
+  <xsl:param name='type' select='substring(concat(../@type,"1"),1,1)' />
+  <xsl:param name='start' select='(text()[normalize-space(.)] | *)[1]' />
+  <xsl:param name='count' select='count(node())' />
+
+  <xsl:apply-templates select='$start'>
+    <xsl:with-param name='list-label'>
+      <xsl:number value='position()' format='{$type}.' />
+    </xsl:with-param>
+  </xsl:apply-templates>
+  <xsl:apply-templates
+    select='$start/following-sibling::node()[$count>position()]' />
+</xsl:template>
+
+<xsl:template match='ol/li|xhtml:ol/xhtml:li'>
+  <xsl:variable name='first' select='(text()[normalize-space(.)] | *)[1]' />
+  <xsl:variable name='firstblock' select='*[f:node-is-block(.)]' />
+
+  <li>
+    <xsl:apply-templates select='@*' />
+    <xsl:choose>
+      <xsl:when test='$first/self::p'>
+        <xsl:call-template name='list-number' />
+      </xsl:when>
+      <xsl:when test='$firstblock' xml:space='preserve'>
+        <p>
+          <xsl:call-template name='list-number' xml:space='default'>
+            <xsl:with-param name='count'
+              select='count($first/following-sibling::*[f:node-is-span(.)])+1' />
+          </xsl:call-template>
+        </p>
+        <xsl:apply-templates
+          select='$firstblock|$firstblock/following-sibling::node()' />
+      </xsl:when>
+      <xsl:otherwise xml:space='preserve'>
+        <p>
+          <xsl:call-template name='list-number' xml:space='default' />
+        </p>
+      </xsl:otherwise>
+    </xsl:choose>
+  </li>
+</xsl:template>
+
+<xsl:template match='ol|xhtml:ol'>
+  <xsl:variable name='type' select='@type' />
+
+  <ul class='ordered'>
+    <xsl:apply-templates select='li | xhtml:li
+        | following-sibling::*[1][self::ol and @start]/li' />
+  </ul>
+</xsl:template>
+<xsl:template match='ol[@start]' />
+
+<!-- Definitions -->
+<!--
+<xsl:template match='ol[starts-with(preceding-sibling::p[1], "Section 1")]'>
+  <dl class='terms'>
+    <xsl:for-each select='li'>
+      <dt><xsl:value-of select='node()[1]' /></dt>
+      <dd><p><xsl:apply-templates select='node()[position()>1]' /></p></dd>
+    </xsl:for-each>
+  </dl>
+</xsl:template>
+-->
+
+<xsl:template match='node()[following-sibling::h3]' />
+<xsl:template match='node()[preceding-sibling::p[@class="shaded"]]' />
+<xsl:template match='node()[@class="shaded"]' />
+<xsl:template match='node()[following-sibling::xhtml:h3]' />
+<xsl:template match='xhtml:blockquote' />
+
+<xsl:template mode='toplevel' match='text()|@*' />
+<xsl:template mode='toplevel' match='*[@id="deed-main-content"]/node()'>
+  <xsl:apply-templates select='.' />
+</xsl:template>
+
+<func:function name='f:node-is-block'>
+  <xsl:param name='node' select='.' />
+  <xsl:variable name='tag' select='local-name($node)' />
+
+  <!-- XXX incomplete -->
+  <func:result select='starts-with($tag, "h") or $tag="div" or $tag="p"
+                       or $tag="ul" or $tag="ol" or $tag="blockquote"' />
+</func:function>
+
+<func:function name='f:node-is-span'>
+  <xsl:param name='node' select='.' />
+
+  <xsl:choose>
+    <xsl:when test='$node/self::text()'>
+      <func:result select='normalize-space($node)' />
+    </xsl:when>
+    <xsl:otherwise>
+      <func:result select='not(f:node-is-block($node))' />
+    </xsl:otherwise>
+  </xsl:choose>
+</func:function>
+
+<func:function name='f:consecutive-spans'>
+  <xsl:param name='start' select='.' />
+  <xsl:param name='next' select='$start/following-sibling::node()[1]' />
+
+  <xsl:choose>
+    <xsl:when test='f:node-is-span($start)'>
+      <func:result select='$start | f:consecutive-spans($next)' />
+    </xsl:when>
+    <xsl:otherwise>
+      <func:result select='/..' />
+    </xsl:otherwise>
+  </xsl:choose>
+</func:function>
+
+<xsl:template mode='toplevel' match='*[@id="deed-main-content"]/node()[f:node-is-span(.)]'>
+  <xsl:variable name='prev' select='preceding-sibling::node()[1]' />
+
+  <xsl:if test='not(f:node-is-span($prev) or self::img)'>
+    <p>
+      <xsl:apply-templates select='f:consecutive-spans(.)' />
+    </p>
+  </xsl:if>
+</xsl:template>
+
+<xsl:template match='/'>
+  <xsl:apply-templates mode='toplevel' select='*' />
+</xsl:template>
+
+</xsl:stylesheet>