@@ -35,6 +35,11 @@ defmodule SpeechMarkdown.Transpiler do
35
35
|> opt_strip_declaration ( xml_declaration ) }
36
36
end
37
37
38
+ ### EMPTY BLOCK
39
+ defp convert ( { :nested_block , nodes , :empty_block } , variant ) do
40
+ Enum . map ( nodes , & convert ( & 1 , variant ) )
41
+ end
42
+
38
43
### BREAK
39
44
40
45
defp convert ( { :kv_block , [ { "break" , break } ] } , _variant ) do
@@ -60,7 +65,18 @@ defmodule SpeechMarkdown.Transpiler do
60
65
61
66
### SECTIONS
62
67
63
- defp convert ( { :section , block , nodes } , :alexa ) do
68
+ defp convert ( { :section , [ { _ , _ } | _ ] = attrs , nodes } , :alexa ) do
69
+ { alexa_attrs , attrs } =
70
+ Enum . split_with ( attrs , & ( elem ( & 1 , 0 ) in ~w( excited disappointed) ) )
71
+
72
+ nodes
73
+ |> Enum . map ( & convert ( & 1 , :alexa ) )
74
+ |> wrap_with_voice_and_or_lang ( attrs )
75
+ |> Alexa . emotion ( alexa_attrs )
76
+ |> unwrap_single_node ( )
77
+ end
78
+
79
+ defp convert ( { :section , block , nodes } , :alexa ) when is_binary ( block ) do
64
80
nodes
65
81
|> Enum . map ( & convert ( & 1 , :alexa ) )
66
82
|> Alexa . emotion ( block )
@@ -102,6 +118,74 @@ defmodule SpeechMarkdown.Transpiler do
102
118
Enum . map ( nodes , & convert ( & 1 , variant ) )
103
119
end
104
120
121
+ ### WHISPER
122
+ defp convert ( { :nested_block , nodes , { :block , "whisper" } } , :alexa ) do
123
+ nodes = Enum . map ( nodes , & convert ( & 1 , :alexa ) )
124
+ { :"amazon:effect" , [ name: 'whispered' ] , nodes }
125
+ end
126
+
127
+ defp convert ( { :nested_block , nodes , { :block , "whisper" } } , variant ) do
128
+ nodes = Enum . map ( nodes , & convert ( & 1 , variant ) )
129
+ { :prosody , [ volume: 'x-soft' , rate: 'slow' ] , nodes }
130
+ end
131
+
132
+ ### PROSODY
133
+
134
+ defp convert (
135
+ { :nested_block , nodes , { :kv_block , [ { "volume" , volume } ] } } ,
136
+ variant
137
+ ) do
138
+ { :prosody , [ volume: volume ] , Enum . map ( nodes , & convert ( & 1 , variant ) ) }
139
+ end
140
+
141
+ defp convert (
142
+ { :nested_block , nodes , { :kv_block , [ { "pitch" , pitch } ] } } ,
143
+ variant
144
+ ) do
145
+ { :prosody , [ pitch: pitch ] , Enum . map ( nodes , & convert ( & 1 , variant ) ) }
146
+ end
147
+
148
+ defp convert (
149
+ { :nested_block , nodes , { :kv_block , [ { "rate" , rate } ] } } ,
150
+ variant
151
+ ) do
152
+ { :prosody , [ rate: rate ] , Enum . map ( nodes , & convert ( & 1 , variant ) ) }
153
+ end
154
+
155
+ ### LANG
156
+
157
+ defp convert ( { :nested_block , nodes , { :kv_block , [ { "lang" , _ } ] } } , :google ) do
158
+ Enum . map ( nodes , & convert ( & 1 , :google ) )
159
+ end
160
+
161
+ defp convert ( { :nested_block , nodes , { :kv_block , [ { "lang" , lang } ] } } , variant ) do
162
+ { :lang , [ "xml:lang": ch ( lang ) ] , Enum . map ( nodes , & convert ( & 1 , variant ) ) }
163
+ end
164
+
165
+ ### SUB
166
+
167
+ defp convert ( { :nested_block , nodes , { :kv_block , [ { "sub" , sub } ] } } , variant ) do
168
+ { :sub , [ alias: ch ( sub ) ] , Enum . map ( nodes , & convert ( & 1 , variant ) ) }
169
+ end
170
+
171
+ ### VOICE
172
+
173
+ defp convert ( { :nested_block , nodes , { :kv_block , [ { "voice" , voice } ] } } , :alexa ) do
174
+ nodes = Enum . map ( nodes , & convert ( & 1 , :alexa ) )
175
+
176
+ case Validator . alexa_voice ( voice ) do
177
+ nil ->
178
+ nodes
179
+
180
+ voice ->
181
+ { :voice , [ name: ch ( voice ) ] , nodes }
182
+ end
183
+ end
184
+
185
+ defp convert ( { :nested_block , nodes , { :kv_block , [ { "voice" , _ } ] } } , variant ) do
186
+ Enum . map ( nodes , & convert ( & 1 , variant ) )
187
+ end
188
+
105
189
### SAY-AS
106
190
defp convert (
107
191
{ :nested_block , nodes , { :kv_block , [ { "emphasis" , level } ] } } ,
@@ -111,23 +195,33 @@ defmodule SpeechMarkdown.Transpiler do
111
195
end
112
196
113
197
defp convert (
114
- { :nested_block , nodes , { :kv_block , [ { "date" , format } ] } } ,
198
+ { :nested_block , nodes , { :kv_block , [ { dt , format } ] } } ,
115
199
variant
116
- ) do
117
- { :"say-as" , [ "interpret-as": 'date' , format: ch ( format ) ] ,
200
+ )
201
+ when dt in ~w( date time) do
202
+ { :"say-as" , [ "interpret-as": ch ( dt ) , format: ch ( format ) ] ,
118
203
Enum . map ( nodes , & convert ( & 1 , variant ) ) }
119
204
end
120
205
121
- @ interpret_as ~w( characters number address chars)
206
+ defp convert ( { :nested_block , nodes , { :block , say } } , :google )
207
+ when say in ~w( interjection) do
208
+ Enum . map ( nodes , & convert ( & 1 , :google ) )
209
+ end
210
+
211
+ @ interpret_as ~w( characters number address chars expletive fraction interjection ordinal unit)
122
212
defp convert ( { :nested_block , nodes , { :block , say } } , variant )
123
213
when say in @ interpret_as do
124
214
{ :"say-as" , [ "interpret-as": say ] , Enum . map ( nodes , & convert ( & 1 , variant ) ) }
125
215
end
126
216
217
+ ### AUDIO
218
+
127
219
defp convert ( { :audio , src } , _variant ) do
128
220
{ :audio , [ src: ch ( src ) ] , [ ] }
129
221
end
130
222
223
+ ### TEXT
224
+
131
225
defp convert ( { :text , text } , _variant ) do
132
226
ch ( text )
133
227
end
@@ -157,4 +251,40 @@ defmodule SpeechMarkdown.Transpiler do
157
251
end
158
252
159
253
defdelegate ch ( s ) , to: String , as: :to_charlist
254
+
255
+ defp wrap_with_voice_and_or_lang ( nodes , attrs ) do
256
+ ~w( lang voice)
257
+ |> Enum . reduce ( nodes , fn
258
+ "lang" , children ->
259
+ case kw ( attrs , "lang" ) do
260
+ nil ->
261
+ children
262
+
263
+ lang ->
264
+ [ { :lang , [ "xml:lang": ch ( lang ) ] , children } ]
265
+ end
266
+
267
+ "voice" , children ->
268
+ case kw ( attrs , "voice" ) do
269
+ nil ->
270
+ children
271
+
272
+ "device" ->
273
+ children
274
+
275
+ voice ->
276
+ [ { :voice , [ name: ch ( voice ) ] , children } ]
277
+ end
278
+ end )
279
+ end
280
+
281
+ defp unwrap_single_node ( [ { _ , _ , _ } = n ] ) , do: n
282
+ defp unwrap_single_node ( n ) , do: n
283
+
284
+ defp kw ( list , prop ) do
285
+ case :proplists . get_value ( prop , list ) do
286
+ :undefined -> nil
287
+ value -> value
288
+ end
289
+ end
160
290
end
0 commit comments