layout '/default.xml'
layout '/default.xsl'
filter :relativize_paths, type: :xml
+ filter :remove_wj
write to_xhtml
end
layout '/default.xml'
layout '/default.xsl'
filter :relativize_paths, type: :xml
+ filter :remove_wj
write to_xhtml
end
layout '/default.xml'
layout '/default.xsl'
filter :relativize_paths, type: :xml
+ filter :remove_wj
write to_xhtml
end
<?xml version='1.0' encoding='UTF-8' ?>
<!--
- Nick's web site: Final XHTML output stage
+ Nick's web site: XHTML output stage
- Copyright © 2018 Nick Bowler
+ Copyright © 2018-2019 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
extension-element-prefixes='func f'
exclude-result-prefixes='xhtml'>
+<xsl:import href='layouts/functions.xsl' />
+
<xsl:output method='xml' encoding='UTF-8' indent='yes'
doctype-public='-//W3C//DTD XHTML 1.1//EN'
doctype-system='http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd' />
-<xsl:strip-space elements='*' />
-<xsl:preserve-space elements='xhtml:p' />
<xsl:param name='source-uri'
select='"//git.draconx.ca/gitweb/homepage.git/blob/"' />
<xsl:copy><xsl:apply-templates select='node()|@*' /></xsl:copy>
</xsl:template>
+<!--
+ Nokogiri's pretty-printer is a bit weird. Regardless of the indentation
+ setting, if an element has no child text nodes then it will be pretty-
+ printed. This works by adding arbitrary whitespace to that element, and
+ then all of its children are eligible to be pretty-printed.
+
+ If an element has any text nodes at all, then it is not pretty-printed and
+ neither are any of its descendents.
+
+ Adding arbitrary whitespace to <pre> is bad, so we inject zero-width non-
+ breaking spaces to prevent this. This will render fine but the spaces
+ should be removed before final output to avoid problems with copy+paste.
+-->
+<xsl:template match='xhtml:pre'>
+ <xsl:copy>
+ <xsl:apply-templates select='node()|@*' />
+ <xsl:text>⁠</xsl:text>
+ </xsl:copy>
+</xsl:template>
+
+<!--
+ Likewise, adding spaces between consecutive span-level elements where
+ none existed before won't go over well.
+-->
+<xsl:template name='glue-preceding-span'>
+ <xsl:if test='f:element-is-span(preceding-sibling::node()[1])'>
+ <xsl:text>⁠</xsl:text>
+ </xsl:if>
+</xsl:template>
+
+<xsl:template match='*[f:element-is-span()]'>
+ <xsl:call-template name='glue-preceding-span' />
+ <xsl:copy>
+ <xsl:apply-templates select='node()|@*' />
+ <xsl:text>⁠</xsl:text> <!-- avoid breaking within a span element -->
+ </xsl:copy>
+</xsl:template>
+
+<!--
+ Manually strip whitespace-only text nodes so the pretty printer can do its
+ thing on remaining elements.
+-->
+<xsl:template match='text()[normalize-space(.) = ""]'>
+ <xsl:choose>
+ <!-- preserve anything according to xml:space -->
+ <xsl:when test='ancestor::*[@xml:space][1][@xml:space="preserve"]'>
+ <xsl:copy />
+ </xsl:when>
+ <!-- preserve anything under <pre> -->
+ <xsl:when test='ancestor::xhtml:pre'><xsl:copy /></xsl:when>
+ </xsl:choose>
+</xsl:template>
+
<!-- Add rel attributes to external links -->
<xsl:template match='xhtml:a[starts-with(@href,"http://")
or starts-with(@href,"https://")
--- /dev/null
+<!--
+ Nick's web site: XSLT helper functions.
+
+ Copyright © 2019 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: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'>
+
+<!-- Returns true iff the given element is an XHTML span-level element -->
+<func:function name='f:element-is-span'>
+ <xsl:param name='node' select='.' />
+ <func:result select='$node/self::xhtml:a
+ or $node/self::xhtml:abbr
+ or $node/self::xhtml:acronym
+ or $node/self::xhtml:b
+ or $node/self::xhtml:bdo
+ or $node/self::xhtml:big
+ or $node/self::xhtml:br
+ or $node/self::xhtml:button
+ or $node/self::xhtml:cite
+ or $node/self::xhtml:code
+ or $node/self::xhtml:dfn
+ or $node/self::xhtml:em
+ or $node/self::xhtml:i
+ or $node/self::xhtml:img
+ or $node/self::xhtml:input
+ or $node/self::xhtml:kbd
+ or $node/self::xhtml:label
+ or $node/self::xhtml:map
+ or $node/self::xhtml:object
+ or $node/self::xhtml:q
+ or $node/self::xhtml:samp
+ or $node/self::xhtml:script
+ or $node/self::xhtml:select
+ or $node/self::xhtml:small
+ or $node/self::xhtml:span
+ or $node/self::xhtml:strong
+ or $node/self::xhtml:sub
+ or $node/self::xhtml:sup
+ or $node/self::xhtml:textarea
+ or $node/self::xhtml:time
+ or $node/self::xhtml:tt
+ or $node/self::xhtml:var' />
+</func:function>
+
+<!-- Returns true iff the node is a nonempty text node or a span element -->
+<func:function name='f:node-is-span'>
+ <xsl:param name='node' select='.' />
+ <func:result test='( $node/self::text() and normalize-text($node) )
+ or f:element-is-span($node)' />
+</func:function>
+
+</xsl:stylesheet>
--- /dev/null
+# Nick's web site: remove_wj filter. Delete all zero-width word joiners
+# which were added during XSLT processing.
+#
+# Copyright © 2019 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/>.
+
+class RemoveWJFilter < Nanoc::Filter
+ identifier :remove_wj
+
+ def run(content, params = {})
+ return content.delete "\u2060"
+ end
+end