helpers/mimeXhtmlPart.xsl
author František Kučera <franta-hg@frantovo.cz>
Sun, 16 Oct 2011 20:55:46 +0200
changeset 81 b51ab80c7a9d
parent 80 1f9e5757caf4
child 83 668014315a54
permissions -rwxr-xr-x
Drupal: XSL pro vytváření <p>odstavců</p> z textu přímo uvnitř html/body
hranice mezi odstavci se poznají podle prázdného řádku (případně podle blokového elementu).
Naopak inline elementy jsou zahrnuty do odstavce. Příklad

První odstavec.
Druhý řádek téhož odstavce.

Druhý odstavec obsahující <em>nějaký inline element</em>.
Stále jsme v druhém odstavci.

Třetí odstavec…
<p>skutečný odstavec, jak to má být</p>
Toto už je čtvrtý resp. pátý odstavec, přestože tu nebyl žádný prázdný řádek.
     1 <?xml version="1.0" encoding="UTF-8"?>
     2 <xsl:stylesheet version="2.0"
     3 	xmlns="http://www.w3.org/1999/xhtml"
     4 	xmlns:h="http://www.w3.org/1999/xhtml"
     5 	xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
     6 	xmlns:fn="http://www.w3.org/2005/xpath-functions"
     7 	xmlns:svg="http://www.w3.org/2000/svg"
     8 	xmlns:xs="http://www.w3.org/2001/XMLSchema"
     9 	exclude-result-prefixes="fn h xs">
    10 	<xsl:output 
    11 		method="xml" 
    12 		indent="yes" 
    13 		encoding="UTF-8"		
    14 		doctype-public="-//W3C//DTD XHTML 1.1 plus MathML 2.0 plus SVG 1.1//EN" 
    15 		doctype-system="http://www.w3.org/2002/04/xhtml-math-svg/xhtml-math-svg.dtd"/>
    16 	
    17 		
    18 	<xsl:param name="title"/>
    19 	<xsl:param name="isRoot"/>
    20 	<xsl:param name="urlBase"/>
    21 	<xsl:param name="wwwRead"/>
    22 	<xsl:param name="wwwPost"/>
    23 	
    24 	
    25 	<!-- Celý dokument -->
    26 	<xsl:template match="/">
    27 		<html>
    28 			<head>
    29 				<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=utf-8" />
    30 				<meta http-equiv="X-NNTP-Generated" content="{fn:current-dateTime()}" />
    31 				<xsl:if test="$urlBase">
    32 					<base href="{$urlBase}"/>
    33 				</xsl:if>
    34 				<xsl:if test="$title">
    35 					<title><xsl:value-of select="$title"/></title>
    36 				</xsl:if>
    37 				<style type="text/css">
    38 					body {
    39 						font-family: sans-serif;
    40 						font-size: 16px;
    41 					}
    42 					
    43 					.wwwLinks {
    44 						border-top: 2px solid grey;
    45 						margin-top: 16px;
    46 						font-size: 66%;
    47 					}
    48 					
    49 					blockquote {
    50 						background-color: #eee;
    51 						font-style: italic;
    52 						padding: 2px 20px;
    53 						margin: 10px 32px;
    54 						border-left: 3px solid silver;
    55 					}
    56 					
    57 					pre {
    58 						background-color: #eee;
    59 						padding: 2px 20px;
    60 						margin: 10px 32px;
    61 						border-left: 3px solid #a00;
    62 					}
    63 					
    64 					img {
    65 						margin: 8px;
    66 					}
    67 					
    68 					a img {
    69 						border: none;
    70 					}
    71 					
    72 					/** TODO: smazat */
    73 					.mešuge {
    74 						background-color: #afa;
    75 						border: 1px solid #55f;
    76 					}
    77 				</style>
    78 			</head>
    79 			<body>
    80 				<xsl:if test="$title and $isRoot">
    81 					<h1><xsl:value-of select="$title"/></h1>			
    82 				</xsl:if>
    83 				<xsl:call-template name="zpracujTělo">
    84 					<xsl:with-param name="prvek" select="h:html/h:body/node()[1]"/>
    85 				</xsl:call-template>
    86 				
    87 				<xsl:if test="$wwwRead or $wwwPost">
    88 					<div class="wwwLinks">
    89 						<p>Přístup přes síť www:</p>
    90 						<ul>
    91 							<xsl:if test="$wwwRead"><li><a href="{$wwwRead}">číst tento příspěvek</a></li></xsl:if>
    92 							<xsl:if test="$wwwPost"><li><a href="{$wwwPost}">odpovědět na tento příspěvek</a></li></xsl:if>
    93 						</ul>
    94 					</div>
    95 				</xsl:if>
    96 			</body>
    97 		</html>
    98 	</xsl:template>
    99 	
   100 	
   101 	<!-- Odkazy -->
   102 	<xsl:template match="h:a">
   103 		<a href="{@href}" title="{@title}"><xsl:apply-templates/></a>
   104 	</xsl:template>
   105 	
   106 	
   107 	<!-- Obrázky -->
   108 	<xsl:template match="h:img">
   109 		<img src="{@src}" alt="{@alt}" title="{@title}"><xsl:apply-templates/></img>
   110 	</xsl:template>
   111 	
   112 	<!-- Zkratky -->
   113 	<xsl:template match="h:abbr">
   114 		<abbr title="{@title}"><xsl:apply-templates/></abbr>
   115 	</xsl:template>
   116 	
   117 	
   118 	<!-- Další povolené značky – ostatní odfiltrujeme (zbude z nich jen text) -->
   119 	<xsl:template match="*">
   120 		<xsl:choose>		
   121 			<xsl:when test="
   122 				name() = 'h1' or
   123 				name() = 'h2' or
   124 				name() = 'h3' or
   125 				name() = 'h4' or
   126 				name() = 'h5' or
   127 				name() = 'h6' or
   128 				name() = 'p' or
   129 				name() = 'div' or
   130 				name() = 'br' or
   131 				name() = 'strong' or
   132 				name() = 'em' or
   133 				name() = 'sub' or
   134 				name() = 'sup' or
   135 				name() = 'del' or
   136 				name() = 'ul' or
   137 				name() = 'ol' or
   138 				name() = 'li' or
   139 				name() = 'pre' or
   140 				name() = 'code' or
   141 				name() = 'blockquote'">
   142 				<xsl:element name="{name()}">
   143 					<xsl:apply-templates/>
   144 				</xsl:element>
   145 			</xsl:when>
   146 			<xsl:otherwise>
   147 				<xsl:value-of select="."/>
   148 			</xsl:otherwise>
   149 		</xsl:choose>		
   150     </xsl:template>
   151     
   152     <!-- 
   153     	Z neuzavřeného (nevalidně se vyskytujícího v body) textu uděláme odstavce.
   154     -->
   155 	<xsl:template name="zpracujTělo">
   156 		<xsl:param name="prvek"/>
   157 		<xsl:param name="vnořeno" select="false()"/>
   158 		<xsl:if test="$prvek">
   159 			<xsl:choose>
   160 				<xsl:when test="$prvek/self::text()">
   161 					<!--
   162 						Textový uzel → budeme dělat odstavce
   163 						(rekurzivně se opět zavolá šablona zpracujTělo)
   164 					-->
   165 					<xsl:call-template name="dělejOdstavce">
   166 						<xsl:with-param name="blokTextu" select="$prvek"/>
   167 						<xsl:with-param name="vnořeno" select="$vnořeno"/>
   168 					</xsl:call-template>
   169 					
   170 					<!-- 
   171 					<xsl:variable name="navázat" as="xs:boolean">
   172 						<xsl:call-template name="navázat">
   173 							<xsl:with-param name="blokTextu" select="$prvek"/>
   174 						</xsl:call-template>
   175 					</xsl:variable>
   176 					
   177 					Někdy zpracujTělo dalšího prvku 
   178 					<xsl:if test="not($navázat)">[další:]
   179 						<xsl:call-template name="zpracujTělo">
   180 							<xsl:with-param name="prvek" select="$prvek/following-sibling::node()[1]"/>
   181 							<xsl:with-param name="vnořeno" select="$vnořeno"/>
   182 						</xsl:call-template>
   183 					</xsl:if>
   184 					-->
   185 					
   186 				</xsl:when>
   187 				<xsl:otherwise>
   188 					<!--
   189 						Jiný uzel → aplikujeme obecné šablony
   190 						a zpracujeme následující uzel.
   191 					-->
   192 					<xsl:apply-templates select="$prvek"/>
   193 					<xsl:call-template name="zpracujTělo">
   194 						<xsl:with-param name="prvek" select="$prvek/following-sibling::node()[1]"/>
   195 						<xsl:with-param name="vnořeno" select="$vnořeno"/>
   196 					</xsl:call-template>
   197 				</xsl:otherwise>					
   198 			</xsl:choose>				
   199 		</xsl:if>
   200 	</xsl:template>
   201 	
   202 	<xsl:variable name="oddělovač" select="'\n\s*\n\s*'"/>
   203 	
   204 	<xsl:template name="navázat" as="xs:boolean">
   205 		<xsl:param name="blokTextu"/>
   206 		<xsl:variable name="dalšíUzel" select="$blokTextu/following-sibling::node()[1]"/>
   207 		<xsl:sequence select="
   208 			not(fn:matches($blokTextu, concat('.*', $oddělovač ,'$'))) and
   209 			$dalšíUzel and
   210 			not(
   211 				$dalšíUzel/name() = 'p' or
   212 				$dalšíUzel/name() = 'div' or								
   213 				$dalšíUzel/name() = 'h1' or								
   214 				$dalšíUzel/name() = 'h2' or								
   215 				$dalšíUzel/name() = 'h3' or								
   216 				$dalšíUzel/name() = 'h4' or								
   217 				$dalšíUzel/name() = 'h5' or								
   218 				$dalšíUzel/name() = 'h6' or								
   219 				$dalšíUzel/name() = 'pre' or								
   220 				$dalšíUzel/name() = 'table' or								
   221 				$dalšíUzel/name() = 'blockquote' or								
   222 				$dalšíUzel/name() = 'hr'								
   223 			)
   224 		"/>
   225 	</xsl:template>
   226 	
   227 	<xsl:template name="dělejOdstavce">
   228 		<xsl:param name="blokTextu"/>
   229 		<xsl:param name="vnořeno" select="false()"/>
   230 		
   231 		<xsl:variable name="dalšíUzel" select="$blokTextu/following-sibling::node()[1]"/>
   232 		
   233 		<xsl:variable name="navázat" as="xs:boolean">
   234 			<xsl:call-template name="navázat">
   235 				<xsl:with-param name="blokTextu" select="$blokTextu"/>
   236 			</xsl:call-template>
   237 		</xsl:variable>
   238 		
   239 		<xsl:for-each select="fn:tokenize($blokTextu, $oddělovač)">
   240 			<!-- TODO: ošetřit prázdné odstavce -->
   241 			<xsl:if test="normalize-space(.) or true()">
   242 				<xsl:choose>
   243 					<xsl:when test="$vnořeno">
   244 						[
   245 							<xsl:value-of select="."/>
   246 							<xsl:if test="$navázat and position() = last()">
   247
   248 								<xsl:call-template name="zpracujTělo">
   249 									<xsl:with-param name="prvek" select="$dalšíUzel"/>
   250 									<xsl:with-param name="vnořeno" select="true()"/>
   251 								</xsl:call-template>
   252 							</xsl:if>
   253 						]
   254 						[Avril:]
   255 						<xsl:if test="not($navázat) and position() = last()">
   256 							a→
   257 								<xsl:call-template name="zpracujTělo">
   258 									<xsl:with-param name="prvek" select="$dalšíUzel"/>
   259 									<xsl:with-param name="vnořeno" select="true()"/>
   260 								</xsl:call-template>
   261 						</xsl:if>
   262 					</xsl:when>
   263 					<xsl:otherwise>
   264 						<p class="mešuge">
   265 						{
   266 							<xsl:value-of select="."/>
   267 							<xsl:if test="$navázat and position() = last()">
   268 								s→
   269 								<xsl:call-template name="zpracujTělo">
   270 									<xsl:with-param name="prvek" select="$dalšíUzel"/>
   271 									<xsl:with-param name="vnořeno" select="true()"/>
   272 								</xsl:call-template>
   273 							</xsl:if>
   274 						}
   275 						</p>
   276 						[sk8:]
   277 						<xsl:if test="not($navázat) and position() = last()">
   278
   279 								<xsl:call-template name="zpracujTělo">
   280 									<xsl:with-param name="prvek" select="$dalšíUzel"/>
   281 									<xsl:with-param name="vnořeno" select="false()"/>
   282 								</xsl:call-template>
   283 						</xsl:if>
   284 					</xsl:otherwise>
   285 				</xsl:choose>
   286 			</xsl:if>
   287 		</xsl:for-each>
   288 		
   289 	</xsl:template>
   290     
   291 	
   292 </xsl:stylesheet>