Skip to content

Commit f55d024

Browse files
committed
[mod-nlb] Implement strong, em, u and strike through @text-transform rules
see issue #217
1 parent 98cb180 commit f55d024

File tree

3 files changed

+268
-85
lines changed

3 files changed

+268
-85
lines changed

modules/nlb/book-to-pef/src/main/resources/css/text-formatting.scss

+43
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,49 @@
22
/* Text formatting */
33
/* -------------------------------------------------------------------------- */
44

5+
@text-transform strong {
6+
system: -nlb-indicators;
7+
open: "⠠⠄";
8+
close: "⠠⠄";
9+
}
10+
11+
@text-transform em {
12+
system: -nlb-indicators;
13+
open: "";
14+
close: "";
15+
}
16+
17+
@text-transform u {
18+
system: -nlb-indicators;
19+
open: "";
20+
close: "";
21+
}
22+
23+
@text-transform strike {
24+
system: -nlb-indicators;
25+
open: "⠐⠂";
26+
close: "⠐⠂";
27+
}
28+
29+
strong, b {
30+
text-transform: strong;
31+
:root:not(:has(em, i)) & {
32+
text-transform: em;
33+
}
34+
}
35+
36+
em, i {
37+
text-transform: em;
38+
}
39+
40+
u {
41+
text-transform: u;
42+
}
43+
44+
strike, s {
45+
text-transform: strike;
46+
}
47+
548
sub {
649
// FIXME: use "-louis-sub" when supported
750
text-transform: -louis-emph-4;

modules/nlb/book-to-pef/src/main/resources/xml/block-translate.xsl

+152-56
Original file line numberDiff line numberDiff line change
@@ -10,14 +10,37 @@
1010

1111
<xsl:import href="http://www.daisy.org/pipeline/modules/braille/css-utils/transform/block-translator-template.xsl"/>
1212

13-
<xsl:variable name="em-count" select="count(//html:em | //html:i | //dtb:em | //dtb:i)"/>
1413
<xsl:variable name="main-locale" select="'no'"/>
1514

15+
<xsl:variable name="text-transform-defs" as="element()*">
16+
<!--
17+
Note: requires that the @text-transform rules are defined in the style attribute of the
18+
root element!
19+
-->
20+
<xsl:for-each select="css:parse-stylesheet(/*/@style)[matches(@selector,'^@text-transform')]">
21+
<xsl:variable name="name" as="xs:string" select="replace(@selector,'^@text-transform\s+(.+)$','$1')"/>
22+
<xsl:variable name="props" as="element()*" select="css:parse-declaration-list(@style)"/>
23+
<xsl:if test="$props[@name='system' and @value='-nlb-indicators']">
24+
<css:text-transform name="{$name}">
25+
<xsl:if test="not($props[@name='open'])">
26+
<xsl:message terminate="yes"
27+
select="concat('@text-transform &quot;',$name,'&quot; does not define &quot;open&quot;')"/>
28+
</xsl:if>
29+
<xsl:attribute name="open" select="css:parse-string($props[@name='open']/@value)/@value"/>
30+
<xsl:if test="not($props[@name='open'])">
31+
<xsl:message terminate="yes"
32+
select="concat('@text-transform &quot;',$name,'&quot; does not define &quot;close&quot;')"/>
33+
</xsl:if>
34+
<xsl:attribute name="close" select="css:parse-string($props[@name='close']/@value)/@value"/>
35+
</css:text-transform>
36+
</xsl:if>
37+
</xsl:for-each>
38+
</xsl:variable>
39+
1640
<xsl:param name="text-transform" required="yes"/>
1741

1842
<xsl:template mode="#default before after" match="css:block">
1943
<xsl:param name="context" as="element()"/>
20-
<xsl:param name="result-style" as="element()*" tunnel="yes"/>
2144
<xsl:variable name="text" as="text()*" select="//text()"/>
2245
<xsl:variable name="style" as="xs:string*">
2346
<xsl:apply-templates mode="style"/>
@@ -58,32 +81,149 @@
5881
</xsl:apply-templates>
5982
</xsl:template>
6083

61-
<xsl:template mode="style" match="text()" as="xs:string">
84+
<xsl:template mode="emphasis" match="*" as="xs:string*" priority="1">
85+
<xsl:param name="segments" as="xs:string*" required="yes"/>
6286
<xsl:param name="source-style" as="element()*" tunnel="yes"/>
63-
<xsl:sequence select="css:serialize-declaration-list($source-style[not(@name='word-spacing')
64-
and not(@value=css:initial-value(@name))])"/>
87+
<xsl:variable name="source-style" as="element()*">
88+
<xsl:call-template name="css:computed-properties">
89+
<xsl:with-param name="properties" select="'text-transform'"/>
90+
<xsl:with-param name="context" select="$dummy-element"/>
91+
<xsl:with-param name="cascaded-properties" tunnel="yes"
92+
select="css:deep-parse-stylesheet(@style)[not(@selector)]/css:property"/>
93+
<xsl:with-param name="parent-properties" tunnel="yes" select="$source-style"/>
94+
</xsl:call-template>
95+
</xsl:variable>
96+
<xsl:next-match>
97+
<xsl:with-param name="segments" select="$segments"/>
98+
<xsl:with-param name="source-style" tunnel="yes" select="$source-style"/>
99+
</xsl:next-match>
100+
</xsl:template>
101+
102+
<!--
103+
do not inherit text-transform values strong, em, u and strike, because these values are
104+
handled at the level of the element on which they are specified
105+
-->
106+
<xsl:template match="css:property[@name='text-transform']" mode="css:compute">
107+
<xsl:param name="concretize-inherit" as="xs:boolean"/>
108+
<xsl:param name="concretize-initial" as="xs:boolean"/>
109+
<xsl:param name="validate" as="xs:boolean"/>
110+
<xsl:param name="context" as="element()"/>
111+
<xsl:choose>
112+
<xsl:when test="@value='inherit'">
113+
<xsl:sequence select="."/>
114+
</xsl:when>
115+
<xsl:when test="@value='none'">
116+
<xsl:sequence select="."/>
117+
</xsl:when>
118+
<xsl:otherwise>
119+
<xsl:variable name="parent-computed" as="element()">
120+
<xsl:call-template name="css:parent-property">
121+
<xsl:with-param name="property" select="@name"/>
122+
<xsl:with-param name="compute" select="true()"/>
123+
<xsl:with-param name="concretize-inherit" select="true()"/>
124+
<xsl:with-param name="concretize-initial" select="$concretize-initial"/>
125+
<xsl:with-param name="validate" select="$validate"/>
126+
<xsl:with-param name="context" select="$context"/>
127+
</xsl:call-template>
128+
</xsl:variable>
129+
<xsl:variable name="parent-computed-value" as="xs:string*"
130+
select="tokenize(normalize-space($parent-computed/@value),' ')[not(.=('strong','em','u','strike'))]"/>
131+
<xsl:variable name="parent-computed" as="element()?">
132+
<xsl:if test="exists($parent-computed-value)">
133+
<xsl:sequence select="css:property(@name, string-join($parent-computed-value,' '))"/>
134+
</xsl:if>
135+
</xsl:variable>
136+
<xsl:choose>
137+
<xsl:when test="not(exists($parent-computed))">
138+
<xsl:sequence select="."/>
139+
</xsl:when>
140+
<xsl:when test="@value=('initial','auto') and $parent-computed/@value='none'">
141+
<xsl:sequence select="."/>
142+
</xsl:when>
143+
<xsl:when test="@value=('initial','auto')">
144+
<xsl:sequence select="$parent-computed"/>
145+
</xsl:when>
146+
<xsl:when test="$parent-computed/@value=('auto','none','initial')">
147+
<xsl:sequence select="."/>
148+
</xsl:when>
149+
<xsl:otherwise>
150+
<xsl:sequence select="css:property(
151+
@name,
152+
string-join(
153+
distinct-values((
154+
tokenize(normalize-space(@value), ' '),
155+
tokenize(normalize-space($parent-computed/@value), ' '))),
156+
' '))"/>
157+
</xsl:otherwise>
158+
</xsl:choose>
159+
</xsl:otherwise>
160+
</xsl:choose>
65161
</xsl:template>
66162

163+
<!--
164+
properties that should not be passed to the Java part of the translator
165+
1) word-spacing handled later in formatter
166+
2) text-transform=strong|em|u|strike handled in the XSLT part
167+
168+
-->
169+
<xsl:template mode="style" match="text()" as="xs:string">
170+
<xsl:param name="source-style" as="element()*" tunnel="yes"/> <!-- css:property* -->
171+
<xsl:variable name="source-style" as="element()*"
172+
select="for $p in $source-style
173+
return if ($p/@name='text-transform')
174+
then css:property('text-transform',
175+
string-join(
176+
tokenize(normalize-space($p/@value),' ')[not(.=('strong','em','u','strike'))],
177+
' '))
178+
[not(@value='')]
179+
else $p"/>
180+
<xsl:sequence select="css:serialize-declaration-list(
181+
$source-style[not(@name='word-spacing')
182+
and not(@value=css:initial-value(@name))])"/>
183+
</xsl:template>
184+
185+
<!--
186+
properties handled by this translator
187+
-->
67188
<xsl:template mode="translate-style"
68189
match="css:property[@name=('letter-spacing',
69190
'font-style',
70191
'font-weight',
71192
'text-decoration',
193+
'text-transform',
72194
'color')]"/>
73195

74196
<xsl:template mode="translate-style" match="css:property[@name='hyphens' and @value='auto']">
75197
<css:property name="hyphens" value="manual"/>
76198
</xsl:template>
77199

200+
<xsl:template mode="translate-style" match="css:rule[matches(@selector,'^@text-transform')]"/>
201+
78202
<xsl:template match="*" mode="emphasis" as="xs:string*">
79203
<xsl:param name="segments" as="xs:string*" required="yes"/>
80-
<xsl:variable name="text-node-count" select="count(.//text())"/>
81-
<xsl:apply-templates select="child::node()[1]" mode="#current">
82-
<xsl:with-param name="segments" select="$segments[position()&lt;=$text-node-count]"/>
83-
</xsl:apply-templates>
84-
<xsl:apply-templates select="following-sibling::node()[1]" mode="#current">
85-
<xsl:with-param name="segments" select="$segments[position()&gt;$text-node-count]"/>
86-
</xsl:apply-templates>
204+
<xsl:param name="source-style" as="element()*" tunnel="yes"/> <!-- css:property* -->
205+
<xsl:choose>
206+
<xsl:when test="$source-style[@name='text-transform'
207+
and tokenize(normalize-space(@value),' ')=$text-transform-defs/@name]">
208+
<xsl:variable name="text-transform" as="xs:string" select="$source-style[@name='text-transform']/@value"/>
209+
<xsl:variable name="text-transform-def" as="element()"
210+
select="$text-transform-defs[@name=tokenize(normalize-space($text-transform),' ')][1]"/>
211+
<xsl:call-template name="mark-emphasis">
212+
<xsl:with-param name="segments" select="$segments"/>
213+
<xsl:with-param name="opening-mark" select="$text-transform-def/@open"/>
214+
<xsl:with-param name="closing-mark" select="$text-transform-def/@close"/>
215+
</xsl:call-template>
216+
</xsl:when>
217+
<xsl:otherwise>
218+
<xsl:variable name="text-node-count" select="count(.//text())"/>
219+
<xsl:apply-templates select="child::node()[1]" mode="#current">
220+
<xsl:with-param name="segments" select="$segments[position()&lt;=$text-node-count]"/>
221+
</xsl:apply-templates>
222+
<xsl:apply-templates select="following-sibling::node()[1]" mode="#current">
223+
<xsl:with-param name="segments" select="$segments[position()&gt;$text-node-count]"/>
224+
</xsl:apply-templates>
225+
</xsl:otherwise>
226+
</xsl:choose>
87227
</xsl:template>
88228

89229
<xsl:template match="text()" mode="emphasis" as="xs:string*">
@@ -142,48 +282,4 @@
142282
</xsl:apply-templates>
143283
</xsl:template>
144284

145-
<!-- treat italic in html and dtbook -->
146-
147-
<xsl:template match="html:em | html:i | dtb:em | dtb:i" mode="emphasis" as="xs:string*">
148-
<xsl:param name="segments" as="xs:string*" required="yes"/>
149-
<xsl:call-template name="mark-emphasis">
150-
<xsl:with-param name="segments" select="$segments"/>
151-
<xsl:with-param name="opening-mark" select="'⠆'"/>
152-
<xsl:with-param name="closing-mark" select="'⠰'"/>
153-
</xsl:call-template>
154-
</xsl:template>
155-
156-
<!-- treat underline in html and dtbook -->
157-
158-
<xsl:template match="html:u | dtb:u" mode="emphasis" as="xs:string*">
159-
<xsl:param name="segments" as="xs:string*" required="yes"/>
160-
<xsl:call-template name="mark-emphasis">
161-
<xsl:with-param name="segments" select="$segments"/>
162-
<xsl:with-param name="opening-mark" select="'⠸'"/>
163-
<xsl:with-param name="closing-mark" select="'⠸'"/>
164-
</xsl:call-template>
165-
</xsl:template>
166-
167-
<!-- treat strikeline in html and dtbook -->
168-
169-
<xsl:template match="html:strike | html:s | dtb:strike | dtb:s" mode="emphasis" as="xs:string*">
170-
<xsl:param name="segments" as="xs:string*" required="yes"/>
171-
<xsl:call-template name="mark-emphasis">
172-
<xsl:with-param name="segments" select="$segments"/>
173-
<xsl:with-param name="opening-mark" select="'⠐⠂'"/>
174-
<xsl:with-param name="closing-mark" select="'⠐⠂'"/>
175-
</xsl:call-template>
176-
</xsl:template>
177-
178-
<!-- treat bold/strong in html and dtbook -->
179-
180-
<xsl:template match="html:strong | html:b | dtb:strong | dtb:b" mode="emphasis" as="xs:string*">
181-
<xsl:param name="segments" as="xs:string*" required="yes"/>
182-
<xsl:call-template name="mark-emphasis">
183-
<xsl:with-param name="segments" select="$segments"/>
184-
<xsl:with-param name="opening-mark" select="if ($em-count=0) then '⠆' else '⠠⠄'"/>
185-
<xsl:with-param name="closing-mark" select="if ($em-count=0) then '⠰' else '⠠⠄'"/>
186-
</xsl:call-template>
187-
</xsl:template>
188-
189285
</xsl:stylesheet>

0 commit comments

Comments
 (0)