helpers/mimeXhtmlPart-make-paragraphs.xsl
author František Kučera <franta-hg@frantovo.cz>
Wed, 31 Dec 2014 12:07:40 +0100
changeset 120 bb1c8a7b774c
parent 119 f5b57e221e38
permissions -rwxr-xr-x
XSLT: licence – GNU GPLv3
franta-hg@81
     1
<?xml version="1.0" encoding="UTF-8"?>
franta-hg@120
     2
<!--
franta-hg@120
     3
Copyright © 2014 František Kučera (frantovo.cz)
franta-hg@120
     4
franta-hg@120
     5
This program is free software: you can redistribute it and/or modify
franta-hg@120
     6
it under the terms of the GNU General Public License as published by
franta-hg@120
     7
the Free Software Foundation, either version 3 of the License, or
franta-hg@120
     8
(at your option) any later version.
franta-hg@120
     9
franta-hg@120
    10
This program is distributed in the hope that it will be useful,
franta-hg@120
    11
but WITHOUT ANY WARRANTY; without even the implied warranty of
franta-hg@120
    12
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
franta-hg@120
    13
GNU General Public License for more details.
franta-hg@120
    14
franta-hg@120
    15
You should have received a copy of the GNU General Public License
franta-hg@120
    16
along with this program.  If not, see <http://www.gnu.org/licenses/>.
franta-hg@120
    17
-->
franta-hg@81
    18
<xsl:stylesheet version="2.0"
franta-hg@81
    19
	xmlns="http://www.w3.org/1999/xhtml"
franta-hg@81
    20
	xmlns:h="http://www.w3.org/1999/xhtml"
franta-hg@81
    21
	xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
franta-hg@81
    22
	xmlns:fn="http://www.w3.org/2005/xpath-functions"
franta-hg@81
    23
	xmlns:xs="http://www.w3.org/2001/XMLSchema"
franta-hg@81
    24
	xmlns:o="https://trac.frantovo.cz/odstavcovac-TODO-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX-/wiki/xmlns/odstavcovac"
franta-hg@83
    25
	exclude-result-prefixes="fn h xs o">
franta-hg@86
    26
	<xsl:output method="xml" indent="yes" encoding="UTF-8" omit-xml-declaration="yes"/>
franta-hg@81
    27
	
franta-hg@83
    28
	<xsl:param name="cssTřída"/>
franta-hg@81
    29
	
franta-hg@81
    30
	<!-- Celý dokument -->
franta-hg@81
    31
	<xsl:template match="/">
franta-hg@81
    32
		<html>
franta-hg@81
    33
			<body>
franta-hg@81
    34
			
franta-hg@81
    35
				<xsl:variable name="prvníKolo">
franta-hg@81
    36
					<xsl:apply-templates select="h:html/h:body/node()" mode="prvníKolo"/>
franta-hg@81
    37
				</xsl:variable>
franta-hg@81
    38
				
franta-hg@81
    39
				<xsl:variable name="druhéKolo">
franta-hg@81
    40
					<xsl:apply-templates select="$prvníKolo" mode="druhéKolo"/>
franta-hg@81
    41
				</xsl:variable>
franta-hg@81
    42
				
franta-hg@81
    43
				<xsl:apply-templates select="$druhéKolo" mode="třetíKolo"/>
franta-hg@81
    44
				
franta-hg@81
    45
			</body>
franta-hg@81
    46
		</html>
franta-hg@81
    47
	</xsl:template>
franta-hg@119
    48
franta-hg@119
    49
franta-hg@83
    50
	<!-- Kopírujeme elementy, ale vynecháme nepoužité xmlns deklarace: -->
franta-hg@83
    51
	<xsl:template match="*" mode="kopíruj">
franta-hg@83
    52
		<xsl:element name="{name()}">
franta-hg@83
    53
			<xsl:copy-of select="@*"/>
franta-hg@86
    54
			<xsl:apply-templates mode="kopíruj"/>
franta-hg@83
    55
		</xsl:element>
franta-hg@119
    56
	</xsl:template>
franta-hg@119
    57
franta-hg@119
    58
franta-hg@119
    59
	<!-- Mezi odstavci je prázdný řádek, můžou být mezery/tabulátory. -->
franta-hg@81
    60
	<xsl:variable name="oddělovač" select="'\n\s*\n\s*'"/>
franta-hg@119
    61
franta-hg@119
    62
franta-hg@81
    63
	<!-- Funkce: zda jde o XHTML inline element – může se vyskytovat uvnitř odstavců. -->
franta-hg@81
    64
	<xsl:template name="inlineElement" as="xs:boolean">
franta-hg@81
    65
		<xsl:param name="prvek"/>
franta-hg@81
    66
		<xsl:sequence select="
franta-hg@119
    67
			$prvek/name() = 'a' or
franta-hg@119
    68
			$prvek/name() = 'abbr' or
franta-hg@119
    69
			$prvek/name() = 'acronym' or
franta-hg@119
    70
			$prvek/name() = 'b' or
franta-hg@119
    71
			$prvek/name() = 'br' or
franta-hg@119
    72
			$prvek/name() = 'cite' or
franta-hg@119
    73
			$prvek/name() = 'code' or
franta-hg@119
    74
			$prvek/name() = 'em' or
franta-hg@119
    75
			$prvek/name() = 'i' or
franta-hg@119
    76
			$prvek/name() = 'img' or
franta-hg@81
    77
			$prvek/name() = 'q' or
franta-hg@81
    78
			$prvek/name() = 'span' or
franta-hg@81
    79
			$prvek/name() = 'strong' or
franta-hg@81
    80
			$prvek/name() = 'sub' or
franta-hg@81
    81
			$prvek/name() = 'sup' or
franta-hg@81
    82
			$prvek/name() = 'tt' or
franta-hg@81
    83
			$prvek/name() = 'u' or
franta-hg@81
    84
			$prvek/name() = 'var'
franta-hg@81
    85
			"/>
franta-hg@81
    86
		<!-- …případně další, pokud je budeme chtít podporovat. -->
franta-hg@81
    87
	</xsl:template>
franta-hg@119
    88
franta-hg@119
    89
franta-hg@81
    90
	<!-- Funkce: zda je prvek začátkem odstavce. -->
franta-hg@81
    91
	<xsl:template name="začátekOdstavce" as="xs:boolean">
franta-hg@81
    92
		<xsl:param name="prvek"/>
franta-hg@119
    93
franta-hg@81
    94
		<xsl:variable name="inlineElement" as="xs:boolean">
franta-hg@81
    95
			<xsl:call-template name="inlineElement"><xsl:with-param name="prvek" select="$prvek"/></xsl:call-template>
franta-hg@81
    96
		</xsl:variable>
franta-hg@119
    97
franta-hg@81
    98
		<xsl:variable name="předchůdce" select="$prvek/preceding-sibling::node()[1]"/>
franta-hg@119
    99
franta-hg@81
   100
		<xsl:variable name="inlineElementPředchůdce" as="xs:boolean">
franta-hg@81
   101
			<xsl:call-template name="inlineElement"><xsl:with-param name="prvek" select="$předchůdce"/></xsl:call-template>
franta-hg@81
   102
		</xsl:variable>
franta-hg@119
   103
franta-hg@81
   104
		<xsl:variable name="textovýUzel" select="boolean($prvek/self::text())"/>
franta-hg@119
   105
franta-hg@81
   106
		<xsl:sequence select="
franta-hg@119
   107
			($inlineElement or $textovýUzel)
franta-hg@119
   108
			and
franta-hg@81
   109
			(
franta-hg@81
   110
				($inlineElementPředchůdce and matches($prvek, concat('^', $oddělovač, '.*')))
franta-hg@81
   111
				or
franta-hg@81
   112
				not($inlineElementPředchůdce)
franta-hg@81
   113
				or
franta-hg@81
   114
				not($předchůdce)
franta-hg@81
   115
			)
franta-hg@81
   116
			and
franta-hg@81
   117
			(
franta-hg@81
   118
				not($předchůdce/self::text())
franta-hg@81
   119
				or
franta-hg@81
   120
				matches($předchůdce/self::text(), concat('.*', $oddělovač, '$'))
franta-hg@81
   121
			)
franta-hg@81
   122
			"/>
franta-hg@81
   123
	</xsl:template>
franta-hg@119
   124
franta-hg@119
   125
franta-hg@81
   126
	<!--
franta-hg@81
   127
		V prvním kole zavřeme volný text a inline elementy do značek <o:odstavec typ=""/>,
franta-hg@81
   128
		kde typ může být "začátek", což značí, že se jedná o první část budoucího odstavce <p/>.
franta-hg@81
   129
	-->
franta-hg@81
   130
	<xsl:template match="text()" mode="prvníKolo">
franta-hg@119
   131
franta-hg@81
   132
		<xsl:variable name="začátekOdstavce" as="xs:boolean">
franta-hg@81
   133
			<xsl:call-template name="začátekOdstavce">
franta-hg@81
   134
				<xsl:with-param name="prvek" select="."/>
franta-hg@81
   135
			</xsl:call-template>
franta-hg@81
   136
		</xsl:variable>
franta-hg@119
   137
franta-hg@81
   138
		<xsl:for-each select="fn:tokenize(., $oddělovač)">
franta-hg@81
   139
			<xsl:element name="o:odstavec">
franta-hg@81
   140
				<xsl:if test="$začátekOdstavce or not(position() = 1)">
franta-hg@81
   141
					<xsl:attribute name="typ">začátek</xsl:attribute>
franta-hg@81
   142
				</xsl:if>
franta-hg@81
   143
				<xsl:value-of select="."/>
franta-hg@81
   144
			</xsl:element>
franta-hg@81
   145
		</xsl:for-each>
franta-hg@119
   146
franta-hg@81
   147
	</xsl:template>
franta-hg@119
   148
franta-hg@119
   149
	<!--
franta-hg@81
   150
		Inline elementy zavíráme do <o:odstavec typ=""/>,
franta-hg@81
   151
		ostatní vkládáme, jak jsou.
franta-hg@81
   152
	-->
franta-hg@81
   153
	<xsl:template match="*" mode="prvníKolo">
franta-hg@119
   154
franta-hg@81
   155
		<xsl:variable name="inlineElement" as="xs:boolean">
franta-hg@81
   156
			<xsl:call-template name="inlineElement">
franta-hg@81
   157
				<xsl:with-param name="prvek" select="."/>
franta-hg@81
   158
			</xsl:call-template>
franta-hg@81
   159
		</xsl:variable>
franta-hg@119
   160
franta-hg@81
   161
		<xsl:choose>
franta-hg@81
   162
			<!-- TODO: zvláštní šablona (match="…") pro inline elementy místo větvení? -->
franta-hg@81
   163
			<xsl:when test="$inlineElement">
franta-hg@81
   164
				<xsl:variable name="začátekOdstavce" as="xs:boolean">
franta-hg@81
   165
					<xsl:call-template name="začátekOdstavce">
franta-hg@81
   166
						<xsl:with-param name="prvek" select="."/>
franta-hg@81
   167
					</xsl:call-template>
franta-hg@81
   168
				</xsl:variable>
franta-hg@81
   169
				<xsl:element name="o:odstavec">
franta-hg@81
   170
					<xsl:if test="$začátekOdstavce">
franta-hg@81
   171
						<xsl:attribute name="typ">začátek</xsl:attribute>
franta-hg@81
   172
					</xsl:if>
franta-hg@81
   173
					<xsl:copy-of select="."/>
franta-hg@81
   174
				</xsl:element>
franta-hg@81
   175
			</xsl:when>
franta-hg@119
   176
			<xsl:otherwise>
franta-hg@81
   177
				<xsl:copy-of select="."/>
franta-hg@119
   178
			</xsl:otherwise>
franta-hg@81
   179
		</xsl:choose>
franta-hg@119
   180
franta-hg@81
   181
	</xsl:template>
franta-hg@119
   182
franta-hg@81
   183
	<!-- V druhém kole spojíme jednotlivé části odstavců. -->
franta-hg@81
   184
	<xsl:template match="o:odstavec[@typ='začátek']" mode="druhéKolo">
franta-hg@81
   185
		<o:odstavec>
franta-hg@81
   186
			<xsl:call-template name="spojOdstavce">
franta-hg@81
   187
				<xsl:with-param name="část" select="."/>
franta-hg@81
   188
			</xsl:call-template>
franta-hg@81
   189
		</o:odstavec>
franta-hg@81
   190
	</xsl:template>
franta-hg@81
   191
	<!-- Následující části odstavce přeskočíme – postará se o ně vnitřní smyčka volaná z předchozí šablony. -->
franta-hg@81
   192
	<xsl:template match="o:odstavec" mode="druhéKolo"/>
franta-hg@81
   193
	<!-- Neinline (blokové) elementy vložíme, jak jsou. -->
franta-hg@81
   194
	<xsl:template match="*" mode="druhéKolo">
franta-hg@81
   195
		<xsl:copy-of select="."/>
franta-hg@81
   196
	</xsl:template>
franta-hg@119
   197
franta-hg@119
   198
franta-hg@81
   199
	<!--
franta-hg@81
   200
		Za první část (parametr, <o:odstavec typ="začátek"/>) resp. její vnitřek
franta-hg@81
   201
		připojíme (rekurze) všechny další části téhož odstavce (oddělíme mezerou).
franta-hg@81
   202
		Konec odstavce poznáme tak, že následovník je něco jiného než <o:odstavec/> nebo má atribut typ="začátek".
franta-hg@81
   203
	-->
franta-hg@81
   204
	<xsl:template name="spojOdstavce">
franta-hg@81
   205
		<xsl:param name="část"/>
franta-hg@81
   206
		<xsl:copy-of select="$část/child::node()"/>
franta-hg@81
   207
		<xsl:variable name="následovník" select="$část/following-sibling::node()[1]"/>
franta-hg@81
   208
		<xsl:if test="$následovník/name() = 'o:odstavec' and not($následovník/@typ = 'začátek')">
franta-hg@81
   209
			<xsl:call-template name="spojOdstavce">
franta-hg@81
   210
				<xsl:with-param name="část" select="$následovník"/>
franta-hg@81
   211
			</xsl:call-template>
franta-hg@81
   212
		</xsl:if>
franta-hg@81
   213
	</xsl:template>
franta-hg@119
   214
franta-hg@119
   215
franta-hg@81
   216
	<!-- Ve třetím kole smažeme prázdné mešuge odstavce. -->
franta-hg@81
   217
	<xsl:template mode="třetíKolo" match="o:odstavec[
franta-hg@81
   218
		count(child::node()) = 0 
franta-hg@81
   219
		or 
franta-hg@81
   220
		(
franta-hg@81
   221
			count(child::node()) = 1 
franta-hg@81
   222
			and
franta-hg@81
   223
			text()
franta-hg@81
   224
			and
franta-hg@81
   225
			matches(text(), '^\s*$')
franta-hg@81
   226
		)
franta-hg@81
   227
		]">
franta-hg@119
   228
		<xsl:text> </xsl:text>
franta-hg@81
   229
	</xsl:template>
franta-hg@81
   230
	<!-- Převedeme z <o:odstavec/> na <p/> -->
franta-hg@81
   231
	<xsl:template match="o:odstavec" mode="třetíKolo">
franta-hg@83
   232
		<xsl:element name="p">
franta-hg@83
   233
			<xsl:if test="$cssTřída">
franta-hg@83
   234
				<xsl:attribute name="class"><xsl:value-of select="$cssTřída"/></xsl:attribute>
franta-hg@83
   235
			</xsl:if>
franta-hg@83
   236
			<xsl:apply-templates select="child::node()" mode="kopíruj"/>
franta-hg@83
   237
		</xsl:element>
franta-hg@81
   238
	</xsl:template>
franta-hg@81
   239
	<!-- Všechno ostatní zkopírujeme, jak je. -->
franta-hg@81
   240
	<xsl:template match="*" mode="třetíKolo">
franta-hg@81
   241
		<xsl:copy-of select="."/>
franta-hg@81
   242
	</xsl:template>
franta-hg@119
   243
franta-hg@119
   244
franta-hg@81
   245
</xsl:stylesheet>