ssml-builder-js 2.1.0 → 2.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +81 -10
- package/dist/chunk-NPZ44CHU.mjs +3513 -0
- package/dist/chunk-NPZ44CHU.mjs.map +1 -0
- package/dist/{chunk-I3GP7OJU.mjs → chunk-PSN6XAFF.mjs} +8 -2
- package/dist/chunk-PSN6XAFF.mjs.map +1 -0
- package/dist/core.js +7 -1
- package/dist/core.js.map +1 -1
- package/dist/core.mjs +1 -1
- package/dist/elements.d.mts +72 -0
- package/dist/elements.d.ts +72 -0
- package/dist/elements.js +4583 -0
- package/dist/elements.js.map +1 -0
- package/dist/elements.mjs +1234 -0
- package/dist/elements.mjs.map +1 -0
- package/dist/index.js +7 -1
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/react.d.mts +30 -1
- package/dist/react.d.ts +30 -1
- package/dist/react.js +923 -251
- package/dist/react.js.map +1 -1
- package/dist/react.mjs +573 -3326
- package/dist/react.mjs.map +1 -1
- package/package.json +11 -2
- package/dist/chunk-I3GP7OJU.mjs.map +0 -1
package/dist/react.mjs
CHANGED
|
@@ -1,7 +1,49 @@
|
|
|
1
1
|
"use client";
|
|
2
2
|
import {
|
|
3
|
-
|
|
4
|
-
|
|
3
|
+
BREAK_TIME_DESCRIPTIONS,
|
|
4
|
+
BREAK_TIME_PRESETS,
|
|
5
|
+
DEFAULT_LOCALE,
|
|
6
|
+
EDITOR_COPY,
|
|
7
|
+
EMPHASIS_LEVEL_DESCRIPTIONS,
|
|
8
|
+
EMPHASIS_LEVEL_PRESETS,
|
|
9
|
+
EXPRESS_AS_STYLE_DESCRIPTIONS,
|
|
10
|
+
EXPRESS_AS_STYLE_PRESETS,
|
|
11
|
+
INLINE_BADGE_COPY,
|
|
12
|
+
LANGUAGE_DESCRIPTIONS,
|
|
13
|
+
LANGUAGE_PRESETS,
|
|
14
|
+
OVERLAY_Z_INDEX,
|
|
15
|
+
PROSODY_PITCH_DESCRIPTIONS,
|
|
16
|
+
PROSODY_PITCH_PRESETS,
|
|
17
|
+
PROSODY_RATE_DESCRIPTIONS,
|
|
18
|
+
PROSODY_RATE_PRESETS,
|
|
19
|
+
PROSODY_VOLUME_DESCRIPTIONS,
|
|
20
|
+
PROSODY_VOLUME_PRESETS,
|
|
21
|
+
SAY_AS_DESCRIPTIONS,
|
|
22
|
+
SAY_AS_PRESETS,
|
|
23
|
+
SELECTION_OVERLAY_ABOVE_THRESHOLD_LINES,
|
|
24
|
+
SILENCE_VALUE_DESCRIPTIONS,
|
|
25
|
+
SILENCE_VALUE_PRESETS,
|
|
26
|
+
SSML_ATTRIBUTE_PRESETS,
|
|
27
|
+
SSML_HOVER_COPY,
|
|
28
|
+
buildPartialSsml,
|
|
29
|
+
buildSsml,
|
|
30
|
+
clearSsmlDocument,
|
|
31
|
+
createSsmlInsertionEdit,
|
|
32
|
+
findActiveSsmlTags,
|
|
33
|
+
findSsmlHoverTarget,
|
|
34
|
+
findSsmlVoiceContext,
|
|
35
|
+
formatSsmlHover,
|
|
36
|
+
formatXmlFragment,
|
|
37
|
+
getEditableRegion,
|
|
38
|
+
getEditableText,
|
|
39
|
+
getExpressAsStyleCategory,
|
|
40
|
+
registerSsmlCompletionProvider,
|
|
41
|
+
resolveExpressAsStyles,
|
|
42
|
+
updateEditableText,
|
|
43
|
+
updateTagAttribute,
|
|
44
|
+
validateSsml
|
|
45
|
+
} from "./chunk-NPZ44CHU.mjs";
|
|
46
|
+
import "./chunk-6S5ODO6A.mjs";
|
|
5
47
|
|
|
6
48
|
// packages/ssml-editor-react/src/SsmlEditor.tsx
|
|
7
49
|
import { Fragment, forwardRef, useImperativeHandle } from "react";
|
|
@@ -12,871 +54,6 @@ function isSsmlEditorButtonVisible(buttonVisibility, button) {
|
|
|
12
54
|
return buttonVisibility?.[button] !== false;
|
|
13
55
|
}
|
|
14
56
|
|
|
15
|
-
// packages/ssml-editor-react/src/constants/ssmlPresets.ts
|
|
16
|
-
var ssmlPresets_exports = {};
|
|
17
|
-
__export(ssmlPresets_exports, {
|
|
18
|
-
BREAK_STRENGTH_PRESETS: () => BREAK_STRENGTH_PRESETS,
|
|
19
|
-
BREAK_TIME_DESCRIPTIONS: () => BREAK_TIME_DESCRIPTIONS,
|
|
20
|
-
BREAK_TIME_PRESETS: () => BREAK_TIME_PRESETS,
|
|
21
|
-
EMPHASIS_LEVEL_DESCRIPTIONS: () => EMPHASIS_LEVEL_DESCRIPTIONS,
|
|
22
|
-
EMPHASIS_LEVEL_PRESETS: () => EMPHASIS_LEVEL_PRESETS,
|
|
23
|
-
EXPRESS_AS_ROLE_PRESETS: () => EXPRESS_AS_ROLE_PRESETS,
|
|
24
|
-
EXPRESS_AS_STYLES_BY_VOICE: () => EXPRESS_AS_STYLES_BY_VOICE,
|
|
25
|
-
EXPRESS_AS_STYLE_DESCRIPTIONS: () => EXPRESS_AS_STYLE_DESCRIPTIONS,
|
|
26
|
-
EXPRESS_AS_STYLE_PRESETS: () => EXPRESS_AS_STYLE_PRESETS,
|
|
27
|
-
LANGUAGE_DESCRIPTIONS: () => LANGUAGE_DESCRIPTIONS,
|
|
28
|
-
LANGUAGE_PRESETS: () => LANGUAGE_PRESETS,
|
|
29
|
-
PHONEME_ALPHABET_PRESETS: () => PHONEME_ALPHABET_PRESETS,
|
|
30
|
-
PROSODY_PITCH_DESCRIPTIONS: () => PROSODY_PITCH_DESCRIPTIONS,
|
|
31
|
-
PROSODY_PITCH_PRESETS: () => PROSODY_PITCH_PRESETS,
|
|
32
|
-
PROSODY_RATE_DESCRIPTIONS: () => PROSODY_RATE_DESCRIPTIONS,
|
|
33
|
-
PROSODY_RATE_PRESETS: () => PROSODY_RATE_PRESETS,
|
|
34
|
-
PROSODY_RATE_VALUES: () => PROSODY_RATE_VALUES,
|
|
35
|
-
PROSODY_VOLUME_DESCRIPTIONS: () => PROSODY_VOLUME_DESCRIPTIONS,
|
|
36
|
-
PROSODY_VOLUME_PRESETS: () => PROSODY_VOLUME_PRESETS,
|
|
37
|
-
SAY_AS_DESCRIPTIONS: () => SAY_AS_DESCRIPTIONS,
|
|
38
|
-
SAY_AS_PRESETS: () => SAY_AS_PRESETS,
|
|
39
|
-
SILENCE_TYPE_PRESETS: () => SILENCE_TYPE_PRESETS,
|
|
40
|
-
SILENCE_VALUE_DESCRIPTIONS: () => SILENCE_VALUE_DESCRIPTIONS,
|
|
41
|
-
SILENCE_VALUE_PRESETS: () => SILENCE_VALUE_PRESETS,
|
|
42
|
-
SSML_ATTRIBUTE_PRESETS: () => SSML_ATTRIBUTE_PRESETS,
|
|
43
|
-
SSML_PRESETS: () => SSML_PRESETS,
|
|
44
|
-
SSML_PRESET_EXAMPLES: () => SSML_PRESET_EXAMPLES,
|
|
45
|
-
VISEME_TYPE_PRESETS: () => VISEME_TYPE_PRESETS,
|
|
46
|
-
resolveExpressAsStyles: () => resolveExpressAsStyles
|
|
47
|
-
});
|
|
48
|
-
var SSML_PRESETS = [
|
|
49
|
-
{
|
|
50
|
-
id: "basic",
|
|
51
|
-
label: "Basic speech",
|
|
52
|
-
ssml: '<speak version="1.0" xml:lang="en-US">Hello, world!</speak>',
|
|
53
|
-
description: "A minimal SSML document."
|
|
54
|
-
},
|
|
55
|
-
{
|
|
56
|
-
id: "voice",
|
|
57
|
-
label: "Voice selection",
|
|
58
|
-
ssml: '<speak version="1.0" xml:lang="en-US"><voice name="en-US-JennyNeural">Hello, world!</voice></speak>',
|
|
59
|
-
description: "Speaks text with a selected voice."
|
|
60
|
-
},
|
|
61
|
-
{
|
|
62
|
-
id: "prosody",
|
|
63
|
-
label: "Prosody",
|
|
64
|
-
ssml: '<speak version="1.0" xml:lang="en-US"><prosody rate="fast" pitch="+2st">Hello, world!</prosody></speak>',
|
|
65
|
-
description: "Adjusts the speech rate and pitch."
|
|
66
|
-
}
|
|
67
|
-
];
|
|
68
|
-
var BREAK_TIME_PRESETS = ["500ms", "1s", "2s", "3s"];
|
|
69
|
-
var BREAK_STRENGTH_PRESETS = ["none", "x-weak", "weak", "medium", "strong", "x-strong"];
|
|
70
|
-
var PROSODY_RATE_PRESETS = ["x-slow", "slow", "medium", "fast", "x-fast"];
|
|
71
|
-
var PROSODY_RATE_VALUES = [...PROSODY_RATE_PRESETS, "percentage"];
|
|
72
|
-
var PROSODY_PITCH_PRESETS = ["+2st", "-2st", "0st", "+4st", "-4st", "+8st", "-8st", "+12st", "-12st"];
|
|
73
|
-
var PROSODY_VOLUME_PRESETS = ["silent", "x-soft", "soft", "medium", "loud", "x-loud"];
|
|
74
|
-
var EXPRESS_AS_STYLE_PRESETS = [
|
|
75
|
-
"cheerful",
|
|
76
|
-
"friendly",
|
|
77
|
-
"calm",
|
|
78
|
-
"sad",
|
|
79
|
-
"angry",
|
|
80
|
-
"excited",
|
|
81
|
-
"serious",
|
|
82
|
-
"assistant",
|
|
83
|
-
"chat",
|
|
84
|
-
"customerservice",
|
|
85
|
-
"hopeful",
|
|
86
|
-
"newscast",
|
|
87
|
-
"shouting",
|
|
88
|
-
"terrified",
|
|
89
|
-
"unfriendly",
|
|
90
|
-
"whispering"
|
|
91
|
-
];
|
|
92
|
-
var EXPRESS_AS_STYLES_BY_VOICE = {
|
|
93
|
-
"ja-JP-NanamiNeural": ["chat", "cheerful", "customerservice"],
|
|
94
|
-
"ja-JP-KeitaNeural": [],
|
|
95
|
-
"en-US-JennyNeural": [
|
|
96
|
-
"angry",
|
|
97
|
-
"assistant",
|
|
98
|
-
"chat",
|
|
99
|
-
"cheerful",
|
|
100
|
-
"customerservice",
|
|
101
|
-
"excited",
|
|
102
|
-
"friendly",
|
|
103
|
-
"hopeful",
|
|
104
|
-
"newscast",
|
|
105
|
-
"sad",
|
|
106
|
-
"shouting",
|
|
107
|
-
"terrified",
|
|
108
|
-
"unfriendly",
|
|
109
|
-
"whispering"
|
|
110
|
-
],
|
|
111
|
-
"en-US-GuyNeural": [
|
|
112
|
-
"angry",
|
|
113
|
-
"cheerful",
|
|
114
|
-
"excited",
|
|
115
|
-
"friendly",
|
|
116
|
-
"hopeful",
|
|
117
|
-
"newscast",
|
|
118
|
-
"sad",
|
|
119
|
-
"shouting",
|
|
120
|
-
"terrified",
|
|
121
|
-
"unfriendly",
|
|
122
|
-
"whispering"
|
|
123
|
-
]
|
|
124
|
-
};
|
|
125
|
-
var EXPRESS_AS_STYLES_BY_NORMALIZED_VOICE = new Map(
|
|
126
|
-
Object.entries(EXPRESS_AS_STYLES_BY_VOICE).map(([voiceName, styles]) => [voiceName.toLowerCase(), styles])
|
|
127
|
-
);
|
|
128
|
-
function resolveExpressAsStyles(voiceName, candidates = EXPRESS_AS_STYLE_PRESETS) {
|
|
129
|
-
if (voiceName === void 0) {
|
|
130
|
-
return candidates;
|
|
131
|
-
}
|
|
132
|
-
const supportedStyles = EXPRESS_AS_STYLES_BY_NORMALIZED_VOICE.get(voiceName.trim().toLowerCase());
|
|
133
|
-
if (supportedStyles === void 0) {
|
|
134
|
-
return candidates;
|
|
135
|
-
}
|
|
136
|
-
const supportedStyleSet = new Set(supportedStyles);
|
|
137
|
-
return candidates.filter((style) => supportedStyleSet.has(style));
|
|
138
|
-
}
|
|
139
|
-
var EXPRESS_AS_ROLE_PRESETS = [
|
|
140
|
-
"Girl",
|
|
141
|
-
"Boy",
|
|
142
|
-
"YoungAdultFemale",
|
|
143
|
-
"YoungAdultMale",
|
|
144
|
-
"OlderAdultFemale",
|
|
145
|
-
"OlderAdultMale",
|
|
146
|
-
"SeniorFemale",
|
|
147
|
-
"SeniorMale"
|
|
148
|
-
];
|
|
149
|
-
var EMPHASIS_LEVEL_PRESETS = ["strong", "moderate", "reduced", "none"];
|
|
150
|
-
var SAY_AS_PRESETS = [
|
|
151
|
-
"characters",
|
|
152
|
-
"spell-out",
|
|
153
|
-
"cardinal",
|
|
154
|
-
"ordinal",
|
|
155
|
-
"number",
|
|
156
|
-
"date",
|
|
157
|
-
"time",
|
|
158
|
-
"telephone",
|
|
159
|
-
"fraction",
|
|
160
|
-
"address",
|
|
161
|
-
"name",
|
|
162
|
-
"currency"
|
|
163
|
-
];
|
|
164
|
-
var LANGUAGE_PRESETS = ["ja-JP", "en-US", "de-DE", "fr-FR"];
|
|
165
|
-
var SILENCE_VALUE_PRESETS = ["300ms", "500ms", "1s"];
|
|
166
|
-
var SILENCE_TYPE_PRESETS = [
|
|
167
|
-
"Leading",
|
|
168
|
-
"Tailing",
|
|
169
|
-
"Sentenceboundary",
|
|
170
|
-
"Comma",
|
|
171
|
-
"Semicolon",
|
|
172
|
-
"Enumerationcomma"
|
|
173
|
-
];
|
|
174
|
-
var PHONEME_ALPHABET_PRESETS = ["ipa", "sapi", "ups", "x-sampa"];
|
|
175
|
-
var VISEME_TYPE_PRESETS = ["redlips_front", "FacialExpression"];
|
|
176
|
-
var SSML_ATTRIBUTE_PRESETS = {
|
|
177
|
-
break: {
|
|
178
|
-
strength: BREAK_STRENGTH_PRESETS,
|
|
179
|
-
time: BREAK_TIME_PRESETS
|
|
180
|
-
},
|
|
181
|
-
prosody: {
|
|
182
|
-
rate: PROSODY_RATE_PRESETS,
|
|
183
|
-
pitch: PROSODY_PITCH_PRESETS,
|
|
184
|
-
volume: PROSODY_VOLUME_PRESETS
|
|
185
|
-
},
|
|
186
|
-
"mstts:express-as": {
|
|
187
|
-
style: EXPRESS_AS_STYLE_PRESETS,
|
|
188
|
-
role: EXPRESS_AS_ROLE_PRESETS
|
|
189
|
-
},
|
|
190
|
-
"express-as": {
|
|
191
|
-
style: EXPRESS_AS_STYLE_PRESETS,
|
|
192
|
-
role: EXPRESS_AS_ROLE_PRESETS
|
|
193
|
-
},
|
|
194
|
-
expressAs: {
|
|
195
|
-
style: EXPRESS_AS_STYLE_PRESETS,
|
|
196
|
-
role: EXPRESS_AS_ROLE_PRESETS
|
|
197
|
-
},
|
|
198
|
-
"say-as": {
|
|
199
|
-
"interpret-as": SAY_AS_PRESETS
|
|
200
|
-
},
|
|
201
|
-
sayAs: {
|
|
202
|
-
"interpret-as": SAY_AS_PRESETS
|
|
203
|
-
},
|
|
204
|
-
emphasis: {
|
|
205
|
-
level: EMPHASIS_LEVEL_PRESETS
|
|
206
|
-
},
|
|
207
|
-
lang: {
|
|
208
|
-
"xml:lang": LANGUAGE_PRESETS
|
|
209
|
-
},
|
|
210
|
-
phoneme: {
|
|
211
|
-
alphabet: PHONEME_ALPHABET_PRESETS
|
|
212
|
-
},
|
|
213
|
-
"mstts:silence": {
|
|
214
|
-
type: SILENCE_TYPE_PRESETS,
|
|
215
|
-
value: SILENCE_VALUE_PRESETS
|
|
216
|
-
},
|
|
217
|
-
silence: {
|
|
218
|
-
type: SILENCE_TYPE_PRESETS,
|
|
219
|
-
value: SILENCE_VALUE_PRESETS
|
|
220
|
-
},
|
|
221
|
-
"mstts:viseme": {
|
|
222
|
-
type: VISEME_TYPE_PRESETS
|
|
223
|
-
},
|
|
224
|
-
viseme: {
|
|
225
|
-
type: VISEME_TYPE_PRESETS
|
|
226
|
-
}
|
|
227
|
-
};
|
|
228
|
-
var SSML_PRESET_EXAMPLES = {
|
|
229
|
-
breakTime: "500ms",
|
|
230
|
-
prosodyRate: "fast",
|
|
231
|
-
prosodyPitch: "+2st",
|
|
232
|
-
prosodyVolume: "loud",
|
|
233
|
-
expressAsStyle: "cheerful",
|
|
234
|
-
phonemeAlphabet: "ipa",
|
|
235
|
-
silenceValue: "300ms"
|
|
236
|
-
};
|
|
237
|
-
var BREAK_TIME_DESCRIPTIONS = {
|
|
238
|
-
"500ms": {
|
|
239
|
-
ja: "500\u30DF\u30EA\u79D2\u306E\u7121\u97F3",
|
|
240
|
-
en: "Inserts 500 milliseconds of silence."
|
|
241
|
-
},
|
|
242
|
-
"1s": {
|
|
243
|
-
ja: "1\u79D2\u306E\u7121\u97F3",
|
|
244
|
-
en: "Inserts one second of silence."
|
|
245
|
-
},
|
|
246
|
-
"2s": {
|
|
247
|
-
ja: "2\u79D2\u306E\u7121\u97F3",
|
|
248
|
-
en: "Inserts two seconds of silence."
|
|
249
|
-
},
|
|
250
|
-
"3s": {
|
|
251
|
-
ja: "3\u79D2\u306E\u7121\u97F3",
|
|
252
|
-
en: "Inserts three seconds of silence."
|
|
253
|
-
}
|
|
254
|
-
};
|
|
255
|
-
var EMPHASIS_LEVEL_DESCRIPTIONS = {
|
|
256
|
-
strong: {
|
|
257
|
-
ja: "\u5F37\u3044\u5F37\u8ABF",
|
|
258
|
-
en: "Applies strong emphasis."
|
|
259
|
-
},
|
|
260
|
-
moderate: {
|
|
261
|
-
ja: "\u4E2D\u7A0B\u5EA6\u306E\u5F37\u8ABF",
|
|
262
|
-
en: "Applies moderate emphasis."
|
|
263
|
-
},
|
|
264
|
-
reduced: {
|
|
265
|
-
ja: "\u5F31\u3081\u306E\u5F37\u8ABF",
|
|
266
|
-
en: "Applies reduced emphasis."
|
|
267
|
-
},
|
|
268
|
-
none: {
|
|
269
|
-
ja: "\u5F37\u8ABF\u306A\u3057",
|
|
270
|
-
en: "Applies no emphasis."
|
|
271
|
-
}
|
|
272
|
-
};
|
|
273
|
-
var PROSODY_RATE_DESCRIPTIONS = {
|
|
274
|
-
"x-slow": {
|
|
275
|
-
ja: "\u6700\u3082\u9045\u3044\u901F\u5EA6",
|
|
276
|
-
en: "Uses the slowest speech rate."
|
|
277
|
-
},
|
|
278
|
-
slow: {
|
|
279
|
-
ja: "\u9045\u3044\u901F\u5EA6",
|
|
280
|
-
en: "Uses a slow speech rate."
|
|
281
|
-
},
|
|
282
|
-
medium: {
|
|
283
|
-
ja: "\u6A19\u6E96\u7684\u306A\u901F\u5EA6",
|
|
284
|
-
en: "Uses the standard speech rate."
|
|
285
|
-
},
|
|
286
|
-
fast: {
|
|
287
|
-
ja: "\u901F\u3044\u901F\u5EA6",
|
|
288
|
-
en: "Uses a fast speech rate."
|
|
289
|
-
},
|
|
290
|
-
"x-fast": {
|
|
291
|
-
ja: "\u6700\u3082\u901F\u3044\u901F\u5EA6",
|
|
292
|
-
en: "Uses the fastest speech rate."
|
|
293
|
-
}
|
|
294
|
-
};
|
|
295
|
-
var PROSODY_PITCH_DESCRIPTIONS = {
|
|
296
|
-
"+2st": {
|
|
297
|
-
ja: "\u57FA\u6E96\u306E\u58F0\u306E\u9AD8\u3055\u3088\u308A2\u534A\u97F3\u4E0A",
|
|
298
|
-
en: "Raises the pitch by two semitones."
|
|
299
|
-
},
|
|
300
|
-
"-2st": {
|
|
301
|
-
ja: "\u57FA\u6E96\u306E\u58F0\u306E\u9AD8\u3055\u3088\u308A2\u534A\u97F3\u4E0B",
|
|
302
|
-
en: "Lowers the pitch by two semitones."
|
|
303
|
-
},
|
|
304
|
-
"0st": {
|
|
305
|
-
ja: "\u57FA\u6E96\u306E\u58F0\u306E\u9AD8\u3055",
|
|
306
|
-
en: "Keeps the baseline pitch."
|
|
307
|
-
},
|
|
308
|
-
"+4st": {
|
|
309
|
-
ja: "\u57FA\u6E96\u306E\u58F0\u306E\u9AD8\u3055\u3088\u308A4\u534A\u97F3\u4E0A",
|
|
310
|
-
en: "Raises the pitch by four semitones."
|
|
311
|
-
},
|
|
312
|
-
"-4st": {
|
|
313
|
-
ja: "\u57FA\u6E96\u306E\u58F0\u306E\u9AD8\u3055\u3088\u308A4\u534A\u97F3\u4E0B",
|
|
314
|
-
en: "Lowers the pitch by four semitones."
|
|
315
|
-
},
|
|
316
|
-
"+8st": {
|
|
317
|
-
ja: "\u57FA\u6E96\u306E\u58F0\u306E\u9AD8\u3055\u3088\u308A8\u534A\u97F3\u4E0A",
|
|
318
|
-
en: "Raises the pitch by eight semitones."
|
|
319
|
-
},
|
|
320
|
-
"-8st": {
|
|
321
|
-
ja: "\u57FA\u6E96\u306E\u58F0\u306E\u9AD8\u3055\u3088\u308A8\u534A\u97F3\u4E0B",
|
|
322
|
-
en: "Lowers the pitch by eight semitones."
|
|
323
|
-
},
|
|
324
|
-
"+12st": {
|
|
325
|
-
ja: "\u57FA\u6E96\u306E\u58F0\u306E\u9AD8\u3055\u3088\u308A12\u534A\u97F3\u4E0A",
|
|
326
|
-
en: "Raises the pitch by twelve semitones."
|
|
327
|
-
},
|
|
328
|
-
"-12st": {
|
|
329
|
-
ja: "\u57FA\u6E96\u306E\u58F0\u306E\u9AD8\u3055\u3088\u308A12\u534A\u97F3\u4E0B",
|
|
330
|
-
en: "Lowers the pitch by twelve semitones."
|
|
331
|
-
}
|
|
332
|
-
};
|
|
333
|
-
var PROSODY_VOLUME_DESCRIPTIONS = {
|
|
334
|
-
silent: {
|
|
335
|
-
ja: "\u7121\u97F3",
|
|
336
|
-
en: "Makes the selected text silent."
|
|
337
|
-
},
|
|
338
|
-
"x-soft": {
|
|
339
|
-
ja: "\u6700\u3082\u5C0F\u3055\u3044\u97F3\u91CF",
|
|
340
|
-
en: "Uses the quietest volume."
|
|
341
|
-
},
|
|
342
|
-
soft: {
|
|
343
|
-
ja: "\u5C0F\u3055\u3044\u97F3\u91CF",
|
|
344
|
-
en: "Uses a soft volume."
|
|
345
|
-
},
|
|
346
|
-
medium: {
|
|
347
|
-
ja: "\u6A19\u6E96\u7684\u306A\u97F3\u91CF",
|
|
348
|
-
en: "Uses the standard volume."
|
|
349
|
-
},
|
|
350
|
-
loud: {
|
|
351
|
-
ja: "\u5927\u304D\u3044\u97F3\u91CF",
|
|
352
|
-
en: "Uses a loud volume."
|
|
353
|
-
},
|
|
354
|
-
"x-loud": {
|
|
355
|
-
ja: "\u6700\u3082\u5927\u304D\u3044\u97F3\u91CF",
|
|
356
|
-
en: "Uses the loudest volume."
|
|
357
|
-
}
|
|
358
|
-
};
|
|
359
|
-
var EXPRESS_AS_STYLE_DESCRIPTIONS = {
|
|
360
|
-
cheerful: {
|
|
361
|
-
ja: "\u660E\u308B\u304F\u5143\u6C17\u306A\u30B9\u30BF\u30A4\u30EB",
|
|
362
|
-
en: "Uses a cheerful style."
|
|
363
|
-
},
|
|
364
|
-
friendly: {
|
|
365
|
-
ja: "\u89AA\u3057\u307F\u3084\u3059\u3044\u30B9\u30BF\u30A4\u30EB",
|
|
366
|
-
en: "Uses a friendly style."
|
|
367
|
-
},
|
|
368
|
-
calm: {
|
|
369
|
-
ja: "\u7A4F\u3084\u304B\u306A\u30B9\u30BF\u30A4\u30EB",
|
|
370
|
-
en: "Uses a calm style."
|
|
371
|
-
},
|
|
372
|
-
sad: {
|
|
373
|
-
ja: "\u60B2\u3057\u3052\u306A\u30B9\u30BF\u30A4\u30EB",
|
|
374
|
-
en: "Uses a sad style."
|
|
375
|
-
},
|
|
376
|
-
angry: {
|
|
377
|
-
ja: "\u6012\u3063\u305F\u3088\u3046\u306A\u30B9\u30BF\u30A4\u30EB",
|
|
378
|
-
en: "Uses an angry style."
|
|
379
|
-
},
|
|
380
|
-
excited: {
|
|
381
|
-
ja: "\u8208\u596E\u3057\u305F\u30B9\u30BF\u30A4\u30EB",
|
|
382
|
-
en: "Uses an excited style."
|
|
383
|
-
},
|
|
384
|
-
serious: {
|
|
385
|
-
ja: "\u771F\u5263\u306A\u30B9\u30BF\u30A4\u30EB",
|
|
386
|
-
en: "Uses a serious style."
|
|
387
|
-
},
|
|
388
|
-
assistant: {
|
|
389
|
-
ja: "\u30C7\u30B8\u30BF\u30EB\u30A2\u30B7\u30B9\u30BF\u30F3\u30C8\u5411\u3051\u306E\u30B9\u30BF\u30A4\u30EB",
|
|
390
|
-
en: "Uses a digital assistant style."
|
|
391
|
-
},
|
|
392
|
-
chat: {
|
|
393
|
-
ja: "\u4F1A\u8A71\u5411\u3051\u306E\u30B9\u30BF\u30A4\u30EB",
|
|
394
|
-
en: "Uses a conversational style."
|
|
395
|
-
},
|
|
396
|
-
customerservice: {
|
|
397
|
-
ja: "\u30AB\u30B9\u30BF\u30DE\u30FC\u30B5\u30FC\u30D3\u30B9\u5411\u3051\u306E\u30B9\u30BF\u30A4\u30EB",
|
|
398
|
-
en: "Uses a customer service style."
|
|
399
|
-
},
|
|
400
|
-
hopeful: {
|
|
401
|
-
ja: "\u5E0C\u671B\u306B\u6E80\u3061\u305F\u30B9\u30BF\u30A4\u30EB",
|
|
402
|
-
en: "Uses a hopeful style."
|
|
403
|
-
},
|
|
404
|
-
newscast: {
|
|
405
|
-
ja: "\u30CB\u30E5\u30FC\u30B9\u8AAD\u307F\u4E0A\u3052\u5411\u3051\u306E\u30B9\u30BF\u30A4\u30EB",
|
|
406
|
-
en: "Uses a newscast style."
|
|
407
|
-
},
|
|
408
|
-
shouting: {
|
|
409
|
-
ja: "\u53EB\u3076\u3088\u3046\u306A\u30B9\u30BF\u30A4\u30EB",
|
|
410
|
-
en: "Uses a shouting style."
|
|
411
|
-
},
|
|
412
|
-
terrified: {
|
|
413
|
-
ja: "\u6050\u6016\u306B\u6E80\u3061\u305F\u30B9\u30BF\u30A4\u30EB",
|
|
414
|
-
en: "Uses a terrified style."
|
|
415
|
-
},
|
|
416
|
-
unfriendly: {
|
|
417
|
-
ja: "\u7121\u611B\u60F3\u306A\u30B9\u30BF\u30A4\u30EB",
|
|
418
|
-
en: "Uses an unfriendly style."
|
|
419
|
-
},
|
|
420
|
-
whispering: {
|
|
421
|
-
ja: "\u3055\u3055\u3084\u304F\u3088\u3046\u306A\u30B9\u30BF\u30A4\u30EB",
|
|
422
|
-
en: "Uses a whispering style."
|
|
423
|
-
}
|
|
424
|
-
};
|
|
425
|
-
var SAY_AS_DESCRIPTIONS = {
|
|
426
|
-
characters: {
|
|
427
|
-
ja: "1\u6587\u5B57\u305A\u3064\u306E\u8AAD\u307F\u4E0A\u3052",
|
|
428
|
-
en: "Speaks the characters one by one."
|
|
429
|
-
},
|
|
430
|
-
"spell-out": {
|
|
431
|
-
ja: "\u7DB4\u308A\u306E\u8AAD\u307F\u4E0A\u3052\uFF081\u6587\u5B57\u305A\u3064\uFF09",
|
|
432
|
-
en: "Spells out the text character by character."
|
|
433
|
-
},
|
|
434
|
-
cardinal: {
|
|
435
|
-
ja: "\u57FA\u6570\u3068\u3057\u3066\u306E\u8AAD\u307F\u4E0A\u3052",
|
|
436
|
-
en: "Speaks the value as a cardinal number."
|
|
437
|
-
},
|
|
438
|
-
ordinal: {
|
|
439
|
-
ja: "\u5E8F\u6570\u3068\u3057\u3066\u306E\u8AAD\u307F\u4E0A\u3052",
|
|
440
|
-
en: "Speaks the value as an ordinal number."
|
|
441
|
-
},
|
|
442
|
-
number: {
|
|
443
|
-
ja: "\u6570\u5024\u3068\u3057\u3066\u306E\u8AAD\u307F\u4E0A\u3052",
|
|
444
|
-
en: "Speaks the value as a number."
|
|
445
|
-
},
|
|
446
|
-
date: {
|
|
447
|
-
ja: "\u65E5\u4ED8\u3068\u3057\u3066\u306E\u8AAD\u307F\u4E0A\u3052",
|
|
448
|
-
en: "Speaks the value as a date."
|
|
449
|
-
},
|
|
450
|
-
time: {
|
|
451
|
-
ja: "\u6642\u523B\u3068\u3057\u3066\u306E\u8AAD\u307F\u4E0A\u3052",
|
|
452
|
-
en: "Speaks the value as a time."
|
|
453
|
-
},
|
|
454
|
-
telephone: {
|
|
455
|
-
ja: "\u96FB\u8A71\u756A\u53F7\u3068\u3057\u3066\u306E\u8AAD\u307F\u4E0A\u3052",
|
|
456
|
-
en: "Speaks the value as a telephone number."
|
|
457
|
-
},
|
|
458
|
-
fraction: {
|
|
459
|
-
ja: "\u5206\u6570\u3068\u3057\u3066\u306E\u8AAD\u307F\u4E0A\u3052",
|
|
460
|
-
en: "Speaks the value as a fraction."
|
|
461
|
-
},
|
|
462
|
-
address: {
|
|
463
|
-
ja: "\u4F4F\u6240\u3068\u3057\u3066\u306E\u8AAD\u307F\u4E0A\u3052",
|
|
464
|
-
en: "Speaks the value as an address."
|
|
465
|
-
},
|
|
466
|
-
name: {
|
|
467
|
-
ja: "\u540D\u524D\u3068\u3057\u3066\u306E\u8AAD\u307F\u4E0A\u3052",
|
|
468
|
-
en: "Speaks the value as a name."
|
|
469
|
-
},
|
|
470
|
-
currency: {
|
|
471
|
-
ja: "\u901A\u8CA8\u3068\u3057\u3066\u306E\u8AAD\u307F\u4E0A\u3052",
|
|
472
|
-
en: "Speaks the value as currency."
|
|
473
|
-
}
|
|
474
|
-
};
|
|
475
|
-
var LANGUAGE_DESCRIPTIONS = {
|
|
476
|
-
"ja-JP": {
|
|
477
|
-
ja: "\u65E5\u672C\u8A9E\uFF08\u65E5\u672C\uFF09\u3067\u8AAD\u307F\u4E0A\u3052\u307E\u3059\u3002",
|
|
478
|
-
en: "Speaks the text in Japanese (Japan)."
|
|
479
|
-
},
|
|
480
|
-
"en-US": {
|
|
481
|
-
ja: "\u82F1\u8A9E\uFF08\u7C73\u56FD\uFF09\u3067\u8AAD\u307F\u4E0A\u3052\u307E\u3059\u3002",
|
|
482
|
-
en: "Speaks the text in English (United States)."
|
|
483
|
-
},
|
|
484
|
-
"de-DE": {
|
|
485
|
-
ja: "\u30C9\u30A4\u30C4\u8A9E\uFF08\u30C9\u30A4\u30C4\uFF09\u3067\u8AAD\u307F\u4E0A\u3052\u307E\u3059\u3002",
|
|
486
|
-
en: "Speaks the text in German (Germany)."
|
|
487
|
-
},
|
|
488
|
-
"fr-FR": {
|
|
489
|
-
ja: "\u30D5\u30E9\u30F3\u30B9\u8A9E\uFF08\u30D5\u30E9\u30F3\u30B9\uFF09\u3067\u8AAD\u307F\u4E0A\u3052\u307E\u3059\u3002",
|
|
490
|
-
en: "Speaks the text in French (France)."
|
|
491
|
-
}
|
|
492
|
-
};
|
|
493
|
-
var SILENCE_VALUE_DESCRIPTIONS = {
|
|
494
|
-
"300ms": {
|
|
495
|
-
ja: "\u5148\u982D\u306B300\u30DF\u30EA\u79D2\u306E\u7121\u97F3\u3092\u633F\u5165\u3057\u307E\u3059\u3002",
|
|
496
|
-
en: "Inserts 300 milliseconds of leading silence."
|
|
497
|
-
},
|
|
498
|
-
"500ms": {
|
|
499
|
-
ja: "\u5148\u982D\u306B500\u30DF\u30EA\u79D2\u306E\u7121\u97F3\u3092\u633F\u5165\u3057\u307E\u3059\u3002",
|
|
500
|
-
en: "Inserts 500 milliseconds of leading silence."
|
|
501
|
-
},
|
|
502
|
-
"1s": {
|
|
503
|
-
ja: "\u5148\u982D\u306B1\u79D2\u306E\u7121\u97F3\u3092\u633F\u5165\u3057\u307E\u3059\u3002",
|
|
504
|
-
en: "Inserts one second of leading silence."
|
|
505
|
-
}
|
|
506
|
-
};
|
|
507
|
-
|
|
508
|
-
// packages/ssml-editor-react/src/locales.ts
|
|
509
|
-
var EDITOR_COPY = {
|
|
510
|
-
ja: {
|
|
511
|
-
editorAriaLabel: "SSML\u30A8\u30C7\u30A3\u30BF\u30FC",
|
|
512
|
-
toolbarAriaLabel: "SSML\u30C4\u30FC\u30EB\u30D0\u30FC",
|
|
513
|
-
clearAll: "\u5168\u3066\u30AF\u30EA\u30A2",
|
|
514
|
-
clearAllTitle: "\u97F3\u58F0\u8A2D\u5B9A\u3092\u4FDD\u6301\u3057\u3066XML\u8981\u7D20\u3092\u524A\u9664\u3057\u672C\u6587\u3092\u6B8B\u3059",
|
|
515
|
-
undo: "\u5143\u306B\u623B\u3059",
|
|
516
|
-
undoTitle: "\u76F4\u524D\u306E\u5909\u66F4\u3092\u5143\u306B\u623B\u3059",
|
|
517
|
-
redo: "\u3084\u308A\u76F4\u3059",
|
|
518
|
-
redoTitle: "\u5143\u306B\u623B\u3057\u305F\u5909\u66F4\u3092\u3084\u308A\u76F4\u3059",
|
|
519
|
-
help: "\u8AAC\u660E",
|
|
520
|
-
helpTitle: "\u30DC\u30BF\u30F3\u3068\u30D1\u30E9\u30E1\u30FC\u30BF\u306E\u8AAC\u660E\u3092\u8868\u793A",
|
|
521
|
-
helpHeading: "\u30DC\u30BF\u30F3\u3068\u30D1\u30E9\u30E1\u30FC\u30BF\u306E\u8AAC\u660E",
|
|
522
|
-
helpDescription: "\u5404\u30B3\u30F3\u30C8\u30ED\u30FC\u30EB\u306E\u6A5F\u80FD\u3068\u30D1\u30E9\u30E1\u30FC\u30BF\u3092\u78BA\u8A8D\u3067\u304D\u307E\u3059\u3002",
|
|
523
|
-
parameters: "\u30D1\u30E9\u30E1\u30FC\u30BF",
|
|
524
|
-
format: "\u30D5\u30A9\u30FC\u30DE\u30C3\u30C8",
|
|
525
|
-
formatTitle: "\u672C\u6587\u306EXML\u3092\u6539\u884C\u3057\u3066\u898B\u3084\u3059\u304F\u8868\u793A",
|
|
526
|
-
decorations: "\u88C5\u98FE",
|
|
527
|
-
decorationsShowTitle: "\u30A4\u30F3\u30E9\u30A4\u30F3\u88C5\u98FE\u3092\u8868\u793A",
|
|
528
|
-
decorationsHideTitle: "\u30A4\u30F3\u30E9\u30A4\u30F3\u88C5\u98FE\u3092\u975E\u8868\u793A",
|
|
529
|
-
syntaxError: "\u69CB\u6587\u30A8\u30E9\u30FC",
|
|
530
|
-
selectionActions: "\u9078\u629E\u7BC4\u56F2\u306E\u64CD\u4F5C",
|
|
531
|
-
selectionCountSuffix: "\u6587\u5B57",
|
|
532
|
-
previewSelection: "\u9078\u629E\u90E8\u5206\u3092\u8A66\u8074",
|
|
533
|
-
previewSelectionTitle: "\u9078\u629E\u90E8\u5206\u306ESSML\u3092\u8A66\u8074",
|
|
534
|
-
noAvailableOptions: "\u5229\u7528\u53EF\u80FD\u306A\u9078\u629E\u80A2\u304C\u3042\u308A\u307E\u305B\u3093\u3002"
|
|
535
|
-
},
|
|
536
|
-
en: {
|
|
537
|
-
editorAriaLabel: "SSML editor",
|
|
538
|
-
toolbarAriaLabel: "SSML toolbar",
|
|
539
|
-
clearAll: "Clear all",
|
|
540
|
-
clearAllTitle: "Remove non-voice XML elements and keep the text and voice settings",
|
|
541
|
-
undo: "Undo",
|
|
542
|
-
undoTitle: "Undo the last change",
|
|
543
|
-
redo: "Redo",
|
|
544
|
-
redoTitle: "Redo the last undone change",
|
|
545
|
-
help: "Help",
|
|
546
|
-
helpTitle: "Show button and parameter descriptions",
|
|
547
|
-
helpHeading: "Button and parameter descriptions",
|
|
548
|
-
helpDescription: "Review what each control does and its parameters.",
|
|
549
|
-
parameters: "Parameters",
|
|
550
|
-
format: "Format",
|
|
551
|
-
formatTitle: "Format the XML in the editor",
|
|
552
|
-
decorations: "Decorations",
|
|
553
|
-
decorationsShowTitle: "Show inline decorations",
|
|
554
|
-
decorationsHideTitle: "Hide inline decorations",
|
|
555
|
-
syntaxError: "Syntax error",
|
|
556
|
-
selectionActions: "Selection actions",
|
|
557
|
-
selectionCountSuffix: " characters",
|
|
558
|
-
previewSelection: "Preview selection",
|
|
559
|
-
previewSelectionTitle: "Preview the selected SSML",
|
|
560
|
-
noAvailableOptions: "No options are available."
|
|
561
|
-
}
|
|
562
|
-
};
|
|
563
|
-
var INLINE_BADGE_COPY = {
|
|
564
|
-
ja: {
|
|
565
|
-
pause: "\u9593",
|
|
566
|
-
pitch: "\u30D4\u30C3\u30C1\u5909\u5316",
|
|
567
|
-
prosody: "\u58F0\u306E\u8ABF\u6574"
|
|
568
|
-
},
|
|
569
|
-
en: {
|
|
570
|
-
pause: "Pause",
|
|
571
|
-
pitch: "Pitch change",
|
|
572
|
-
prosody: "Prosody"
|
|
573
|
-
}
|
|
574
|
-
};
|
|
575
|
-
var SSML_HOVER_COPY = {
|
|
576
|
-
ja: {
|
|
577
|
-
parameterHeading: "\u30D1\u30E9\u30E1\u30FC\u30BF",
|
|
578
|
-
parametersHeading: "\u30D1\u30E9\u30E1\u30FC\u30BF",
|
|
579
|
-
allowedValues: "\u4F7F\u7528\u3067\u304D\u308B\u5024",
|
|
580
|
-
example: "\u4F8B",
|
|
581
|
-
noParameters: "\u3053\u306E\u8981\u7D20\u306B\u30D1\u30E9\u30E1\u30FC\u30BF\u306F\u3042\u308A\u307E\u305B\u3093\u3002",
|
|
582
|
-
tags: {
|
|
583
|
-
voice: {
|
|
584
|
-
title: "\u97F3\u58F0",
|
|
585
|
-
description: "\u56F2\u307E\u308C\u305F\u30C6\u30AD\u30B9\u30C8\u306E\u5408\u6210\u306B\u4F7F\u7528\u3059\u308B\u97F3\u58F0\u3068\u3001\u4EFB\u610F\u306E\u97F3\u58F0\u52B9\u679C\u3092\u9078\u629E\u3057\u307E\u3059\u3002",
|
|
586
|
-
parameters: {
|
|
587
|
-
name: { title: "name", description: "\u97F3\u58F0\u540D\u3002\u4F8B: `en-US-JennyNeural`\u3002" },
|
|
588
|
-
effect: { title: "effect", description: "\u4EFB\u610F\u306E\u97F3\u58F0\u52B9\u679C\u3002\u4F8B: `eq_car`\u3002" }
|
|
589
|
-
}
|
|
590
|
-
},
|
|
591
|
-
prosody: {
|
|
592
|
-
title: "\u97FB\u5F8B",
|
|
593
|
-
description: "\u56F2\u307E\u308C\u305F\u30C6\u30AD\u30B9\u30C8\u306E\u901F\u5EA6\u3001\u30D4\u30C3\u30C1\u3001\u97F3\u91CF\u3001\u307E\u305F\u306F\u30D4\u30C3\u30C1\u66F2\u7DDA\u3092\u5909\u66F4\u3057\u307E\u3059\u3002",
|
|
594
|
-
parameters: {
|
|
595
|
-
rate: { title: "rate", description: "\u767A\u8A71\u901F\u5EA6\u3092\u6307\u5B9A\u3057\u307E\u3059\u3002" },
|
|
596
|
-
pitch: { title: "pitch", description: "\u540D\u524D\u4ED8\u304D\u306E\u5024\u3001\u5272\u5408\u3001\u5468\u6CE2\u6570\u3001\u307E\u305F\u306F\u534A\u97F3\u3067\u30D4\u30C3\u30C1\u3092\u8ABF\u6574\u3057\u307E\u3059\u3002" },
|
|
597
|
-
volume: { title: "volume", description: "\u540D\u524D\u4ED8\u304D\u306E\u5024\u3001\u5272\u5408\u3001\u307E\u305F\u306F\u30C7\u30B7\u30D9\u30EB\u5024\u3067\u97F3\u91CF\u3092\u6307\u5B9A\u3057\u307E\u3059\u3002" },
|
|
598
|
-
contour: { title: "contour", description: "\u30C6\u30AD\u30B9\u30C8\u5185\u306E\u4F4D\u7F6E\u3054\u3068\u306E\u76F8\u5BFE\u7684\u306A\u30D4\u30C3\u30C1\u5909\u5316\u3092\u5B9A\u7FA9\u3057\u307E\u3059\u3002" },
|
|
599
|
-
range: { title: "range", description: "\u97F3\u58F0\u306E\u30D4\u30C3\u30C1\u7BC4\u56F2\u3092\u8ABF\u6574\u3057\u307E\u3059\u3002" }
|
|
600
|
-
}
|
|
601
|
-
},
|
|
602
|
-
break: {
|
|
603
|
-
title: "\u9593",
|
|
604
|
-
description: "\u5358\u8A9E\u3084\u305D\u306E\u4ED6\u306E\u97F3\u58F0\u30B3\u30F3\u30C6\u30F3\u30C4\u306E\u9593\u306B\u30DD\u30FC\u30BA\u3092\u633F\u5165\u3057\u307E\u3059\u3002",
|
|
605
|
-
parameters: {
|
|
606
|
-
time: { title: "time", description: "\u30DD\u30FC\u30BA\u306E\u9577\u3055\u3002\u4F8B: `500ms` \u307E\u305F\u306F `1s`\u3002" },
|
|
607
|
-
strength: { title: "strength", description: "\u76F8\u5BFE\u7684\u306A\u30DD\u30FC\u30BA\u306E\u5F37\u3055\u3002" }
|
|
608
|
-
}
|
|
609
|
-
},
|
|
610
|
-
"mstts:express-as": {
|
|
611
|
-
title: "\u8868\u73FE",
|
|
612
|
-
description: "\u56F2\u307E\u308C\u305F\u30C6\u30AD\u30B9\u30C8\u306B\u97F3\u58F0\u30B9\u30BF\u30A4\u30EB\u3001\u30B9\u30BF\u30A4\u30EB\u306E\u5F37\u3055\u3001\u307E\u305F\u306F\u5F79\u5272\u3092\u9069\u7528\u3057\u307E\u3059\u3002",
|
|
613
|
-
parameters: {
|
|
614
|
-
style: { title: "style", description: "\u9078\u629E\u3057\u305F\u97F3\u58F0\u304C\u5BFE\u5FDC\u3059\u308B\u97F3\u58F0\u30B9\u30BF\u30A4\u30EB\u3002\u4F8B: `cheerful`\u3002" },
|
|
615
|
-
styledegree: { title: "styledegree", description: "\u9078\u629E\u3057\u305F\u97F3\u58F0\u30B9\u30BF\u30A4\u30EB\u306E\u5F37\u3055\u3092\u6307\u5B9A\u3057\u307E\u3059\u3002" },
|
|
616
|
-
role: { title: "role", description: "\u5BFE\u5FDC\u3057\u3066\u3044\u308B\u5834\u5408\u306B\u97F3\u58F0\u306E\u5F79\u5272\u3092\u5909\u66F4\u3057\u307E\u3059\u3002" }
|
|
617
|
-
}
|
|
618
|
-
},
|
|
619
|
-
"say-as": {
|
|
620
|
-
title: "\u8AAD\u307F\u4E0A\u3052\u65B9",
|
|
621
|
-
description: "\u56F2\u307E\u308C\u305F\u30C6\u30AD\u30B9\u30C8\u306E\u89E3\u91C8\u65B9\u6CD5\u3068\u8AAD\u307F\u4E0A\u3052\u65B9\u3092\u6307\u5B9A\u3057\u307E\u3059\u3002",
|
|
622
|
-
parameters: {
|
|
623
|
-
"interpret-as": { title: "interpret-as", description: "\u6587\u5B57\u3001\u6570\u5B57\u3001\u65E5\u4ED8\u3001\u6642\u523B\u306A\u3069\u306E\u89E3\u91C8\u3092\u6307\u5B9A\u3057\u307E\u3059\u3002" },
|
|
624
|
-
format: { title: "format", description: "\u9078\u629E\u3057\u305F\u89E3\u91C8\u306E\u5F62\u5F0F\u3092\u88DC\u8DB3\u3057\u307E\u3059\u3002" },
|
|
625
|
-
detail: { title: "detail", description: "\u9078\u629E\u3057\u305F\u89E3\u91C8\u306E\u8A73\u7D30\u3092\u88DC\u8DB3\u3057\u307E\u3059\u3002" }
|
|
626
|
-
}
|
|
627
|
-
},
|
|
628
|
-
phoneme: {
|
|
629
|
-
title: "\u97F3\u7D20",
|
|
630
|
-
description: "\u6307\u5B9A\u3057\u305F\u97F3\u7D20\u8868\u8A18\u3067\u901A\u5E38\u306E\u767A\u97F3\u3092\u7F6E\u304D\u63DB\u3048\u307E\u3059\u3002",
|
|
631
|
-
parameters: {
|
|
632
|
-
alphabet: { title: "alphabet", description: "`ph` \u5024\u306B\u4F7F\u7528\u3059\u308B\u97F3\u7D20\u30A2\u30EB\u30D5\u30A1\u30D9\u30C3\u30C8\u3002" },
|
|
633
|
-
ph: { title: "ph", description: "\u56F2\u307E\u308C\u305F\u30C6\u30AD\u30B9\u30C8\u306E\u97F3\u7D20\u8868\u8A18\u3002" }
|
|
634
|
-
}
|
|
635
|
-
},
|
|
636
|
-
emphasis: {
|
|
637
|
-
title: "\u5F37\u8ABF",
|
|
638
|
-
description: "\u56F2\u307E\u308C\u305F\u30C6\u30AD\u30B9\u30C8\u3092\u5F37\u8ABF\u3057\u307E\u3059\u3002",
|
|
639
|
-
parameters: {
|
|
640
|
-
level: { title: "level", description: "\u5F37\u8ABF\u306E\u5EA6\u5408\u3044\u3092\u6307\u5B9A\u3057\u307E\u3059\u3002" }
|
|
641
|
-
}
|
|
642
|
-
},
|
|
643
|
-
audio: {
|
|
644
|
-
title: "\u97F3\u58F0\u30D5\u30A1\u30A4\u30EB",
|
|
645
|
-
description: "\u5408\u6210\u7D50\u679C\u306E\u4E00\u90E8\u3068\u3057\u3066\u97F3\u58F0\u30D5\u30A1\u30A4\u30EB\u3092\u518D\u751F\u3057\u307E\u3059\u3002",
|
|
646
|
-
parameters: {
|
|
647
|
-
src: { title: "src", description: "\u97F3\u58F0\u30D5\u30A1\u30A4\u30EB\u306E URI\u3002" },
|
|
648
|
-
desc: { title: "desc", description: "\u97F3\u58F0\u3092\u518D\u751F\u3067\u304D\u306A\u3044\u5834\u5408\u306B\u4F7F\u7528\u3059\u308B\u4EE3\u66FF\u30C6\u30AD\u30B9\u30C8\u3002" },
|
|
649
|
-
clipBegin: { title: "clipBegin", description: "\u97F3\u58F0\u30D5\u30A1\u30A4\u30EB\u5185\u306E\u958B\u59CB\u4F4D\u7F6E\u3002\u4F8B: `0s`\u3002" },
|
|
650
|
-
clipEnd: { title: "clipEnd", description: "\u97F3\u58F0\u30D5\u30A1\u30A4\u30EB\u5185\u306E\u7D42\u4E86\u4F4D\u7F6E\u3002\u4F8B: `5s`\u3002" },
|
|
651
|
-
speed: { title: "speed", description: "\u97F3\u58F0\u30D5\u30A1\u30A4\u30EB\u306E\u518D\u751F\u901F\u5EA6\u3002\u4F8B: `1.0`\u3002" },
|
|
652
|
-
repeatCount: { title: "repeatCount", description: "\u97F3\u58F0\u3092\u7E70\u308A\u8FD4\u3059\u56DE\u6570\u3002\u4F8B: `2`\u3002" },
|
|
653
|
-
repeatDuration: { title: "repeatDuration", description: "\u97F3\u58F0\u3092\u7E70\u308A\u8FD4\u3059\u5408\u8A08\u6642\u9593\u3002\u4F8B: `10s`\u3002" },
|
|
654
|
-
soundLevel: { title: "soundLevel", description: "\u30C7\u30B7\u30D9\u30EB\u5358\u4F4D\u306E\u97F3\u91CF\u8ABF\u6574\u3002\u4F8B: `-3dB`\u3002" }
|
|
655
|
-
}
|
|
656
|
-
},
|
|
657
|
-
sub: {
|
|
658
|
-
title: "\u7F6E\u63DB",
|
|
659
|
-
description: "\u56F2\u307E\u308C\u305F\u30C6\u30AD\u30B9\u30C8\u306E\u4EE3\u308F\u308A\u306B\u5225\u540D\u30C6\u30AD\u30B9\u30C8\u3092\u8AAD\u307F\u4E0A\u3052\u307E\u3059\u3002",
|
|
660
|
-
parameters: {
|
|
661
|
-
alias: { title: "alias", description: "\u5143\u306E\u30C6\u30AD\u30B9\u30C8\u306E\u4EE3\u308F\u308A\u306B\u8AAD\u307F\u4E0A\u3052\u308B\u30C6\u30AD\u30B9\u30C8\u3002\u4F8B: `World Wide Web`\u3002" }
|
|
662
|
-
}
|
|
663
|
-
},
|
|
664
|
-
lang: {
|
|
665
|
-
title: "\u8A00\u8A9E",
|
|
666
|
-
description: "\u56F2\u307E\u308C\u305F\u30C6\u30AD\u30B9\u30C8\u306E\u8AAD\u307F\u4E0A\u3052\u8A00\u8A9E\u3092\u5909\u66F4\u3057\u307E\u3059\u3002",
|
|
667
|
-
parameters: {
|
|
668
|
-
"xml:lang": { title: "xml:lang", description: "BCP-47 \u8A00\u8A9E\u30BF\u30B0\u3002\u4F8B: `ja-JP`\u3002" }
|
|
669
|
-
}
|
|
670
|
-
},
|
|
671
|
-
mark: {
|
|
672
|
-
title: "\u30DE\u30FC\u30AB\u30FC",
|
|
673
|
-
description: "\u5408\u6210\u97F3\u58F0\u30B9\u30C8\u30EA\u30FC\u30E0\u306B\u30AB\u30B9\u30BF\u30E0\u30DE\u30FC\u30AB\u30FC\u3092\u633F\u5165\u3057\u307E\u3059\u3002",
|
|
674
|
-
parameters: {
|
|
675
|
-
name: { title: "name", description: "\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u3067\u5B9A\u7FA9\u3057\u305F\u30DE\u30FC\u30AB\u30FC\u540D\u3002\u4F8B: `chapter-1`\u3002" }
|
|
676
|
-
}
|
|
677
|
-
},
|
|
678
|
-
bookmark: {
|
|
679
|
-
title: "\u30D6\u30C3\u30AF\u30DE\u30FC\u30AF",
|
|
680
|
-
description: "\u5408\u6210\u97F3\u58F0\u30B9\u30C8\u30EA\u30FC\u30E0\u306B\u30D6\u30C3\u30AF\u30DE\u30FC\u30AF\u30DE\u30FC\u30AB\u30FC\u3092\u633F\u5165\u3057\u307E\u3059\u3002",
|
|
681
|
-
parameters: {
|
|
682
|
-
mark: { title: "mark", description: "\u30A2\u30D7\u30EA\u30B1\u30FC\u30B7\u30E7\u30F3\u3067\u5B9A\u7FA9\u3057\u305F\u30D6\u30C3\u30AF\u30DE\u30FC\u30AF\u540D\u3002\u4F8B: `chapter-1`\u3002" }
|
|
683
|
-
}
|
|
684
|
-
},
|
|
685
|
-
lexicon: {
|
|
686
|
-
title: "\u767A\u97F3\u8F9E\u66F8",
|
|
687
|
-
description: "\u5408\u6210\u6587\u66F8\u306B\u767A\u97F3\u8F9E\u66F8\u3092\u95A2\u9023\u4ED8\u3051\u307E\u3059\u3002",
|
|
688
|
-
parameters: {
|
|
689
|
-
uri: { title: "uri", description: "\u767A\u97F3\u8F9E\u66F8\u306E URI\u3002" }
|
|
690
|
-
}
|
|
691
|
-
},
|
|
692
|
-
p: { title: "\u6BB5\u843D", description: "\u30C6\u30AD\u30B9\u30C8\u3092\u6BB5\u843D\u3068\u3057\u3066\u307E\u3068\u3081\u307E\u3059\u3002", parameters: {} },
|
|
693
|
-
s: { title: "\u6587", description: "\u30C6\u30AD\u30B9\u30C8\u3092\u6587\u3068\u3057\u3066\u307E\u3068\u3081\u307E\u3059\u3002", parameters: {} },
|
|
694
|
-
w: { title: "\u5358\u8A9E", description: "\u30C6\u30AD\u30B9\u30C8\u3092\u5358\u8A9E\u3068\u3057\u3066\u307E\u3068\u3081\u307E\u3059\u3002", parameters: {} },
|
|
695
|
-
"mstts:silence": {
|
|
696
|
-
title: "\u7121\u97F3",
|
|
697
|
-
description: "\u30C6\u30AD\u30B9\u30C8\u306E\u524D\u5F8C\u3001\u307E\u305F\u306F\u53E5\u8AAD\u70B9\u306E\u5883\u754C\u306B\u6307\u5B9A\u3057\u305F\u7121\u97F3\u3092\u8FFD\u52A0\u3057\u307E\u3059\u3002",
|
|
698
|
-
parameters: {
|
|
699
|
-
type: { title: "type", description: "\u7121\u97F3\u306E\u4F4D\u7F6E\u307E\u305F\u306F\u53E5\u8AAD\u70B9\u306E\u5883\u754C\u3002" },
|
|
700
|
-
value: { title: "value", description: "\u7121\u97F3\u306E\u9577\u3055\u3002\u4F8B: `300ms`\u3002" }
|
|
701
|
-
}
|
|
702
|
-
},
|
|
703
|
-
"mstts:viseme": {
|
|
704
|
-
title: "\u30D3\u30BC\u30FC\u30E0",
|
|
705
|
-
description: "\u5408\u6210\u97F3\u58F0\u306E\u30D3\u30BC\u30FC\u30E0\u30A4\u30D9\u30F3\u30C8\u3092\u8981\u6C42\u3057\u307E\u3059\u3002",
|
|
706
|
-
parameters: {
|
|
707
|
-
type: { title: "type", description: "\u30D3\u30BC\u30FC\u30E0\u30A4\u30D9\u30F3\u30C8\u306E\u5F62\u5F0F\u3002" }
|
|
708
|
-
}
|
|
709
|
-
}
|
|
710
|
-
}
|
|
711
|
-
},
|
|
712
|
-
en: {
|
|
713
|
-
parameterHeading: "Parameter",
|
|
714
|
-
parametersHeading: "Parameters",
|
|
715
|
-
allowedValues: "Allowed values",
|
|
716
|
-
example: "Example",
|
|
717
|
-
noParameters: "This element has no parameters.",
|
|
718
|
-
tags: {
|
|
719
|
-
voice: {
|
|
720
|
-
title: "Voice",
|
|
721
|
-
description: "Selects the voice and optional voice effect used to synthesize the enclosed text.",
|
|
722
|
-
parameters: {
|
|
723
|
-
name: { title: "name", description: "The voice name, such as `en-US-JennyNeural`." },
|
|
724
|
-
effect: { title: "effect", description: "An optional voice effect, such as `eq_car`." }
|
|
725
|
-
}
|
|
726
|
-
},
|
|
727
|
-
prosody: {
|
|
728
|
-
title: "Prosody",
|
|
729
|
-
description: "Changes the speaking rate, pitch, volume, or pitch contour of the enclosed text.",
|
|
730
|
-
parameters: {
|
|
731
|
-
rate: { title: "rate", description: "Controls speaking speed." },
|
|
732
|
-
pitch: {
|
|
733
|
-
title: "pitch",
|
|
734
|
-
description: "Adjusts pitch using a named value, percentage, frequency, or semitone value."
|
|
735
|
-
},
|
|
736
|
-
volume: {
|
|
737
|
-
title: "volume",
|
|
738
|
-
description: "Controls loudness using a named value, percentage, or decibel value."
|
|
739
|
-
},
|
|
740
|
-
contour: {
|
|
741
|
-
title: "contour",
|
|
742
|
-
description: "Defines a sequence of relative pitch changes at positions in the text."
|
|
743
|
-
},
|
|
744
|
-
range: { title: "range", description: "Adjusts the pitch range of the voice." }
|
|
745
|
-
}
|
|
746
|
-
},
|
|
747
|
-
break: {
|
|
748
|
-
title: "Break",
|
|
749
|
-
description: "Inserts a pause between words or other spoken content.",
|
|
750
|
-
parameters: {
|
|
751
|
-
time: { title: "time", description: "The pause duration, for example `500ms` or `1s`." },
|
|
752
|
-
strength: { title: "strength", description: "The relative pause strength." }
|
|
753
|
-
}
|
|
754
|
-
},
|
|
755
|
-
"mstts:express-as": {
|
|
756
|
-
title: "Express-as",
|
|
757
|
-
description: "Applies a speaking style, style degree, or role to the enclosed text.",
|
|
758
|
-
parameters: {
|
|
759
|
-
style: {
|
|
760
|
-
title: "style",
|
|
761
|
-
description: "The speaking style supported by the selected voice, such as `cheerful`."
|
|
762
|
-
},
|
|
763
|
-
styledegree: { title: "styledegree", description: "Controls the intensity of the selected speaking style." },
|
|
764
|
-
role: { title: "role", description: "Changes the speaking role when supported by the selected voice." }
|
|
765
|
-
}
|
|
766
|
-
},
|
|
767
|
-
"say-as": {
|
|
768
|
-
title: "Say-as",
|
|
769
|
-
description: "Controls how the enclosed text is interpreted and spoken.",
|
|
770
|
-
parameters: {
|
|
771
|
-
"interpret-as": {
|
|
772
|
-
title: "interpret-as",
|
|
773
|
-
description: "Specifies the interpretation, such as characters, digits, date, or time."
|
|
774
|
-
},
|
|
775
|
-
format: { title: "format", description: "Provides a format hint for the selected interpretation." },
|
|
776
|
-
detail: {
|
|
777
|
-
title: "detail",
|
|
778
|
-
description: "Provides an additional detail hint for the selected interpretation."
|
|
779
|
-
}
|
|
780
|
-
}
|
|
781
|
-
},
|
|
782
|
-
phoneme: {
|
|
783
|
-
title: "Phoneme",
|
|
784
|
-
description: "Replaces normal pronunciation with the supplied phonetic pronunciation.",
|
|
785
|
-
parameters: {
|
|
786
|
-
alphabet: { title: "alphabet", description: "The phonetic alphabet used by the `ph` value." },
|
|
787
|
-
ph: { title: "ph", description: "The phonetic pronunciation for the enclosed text." }
|
|
788
|
-
}
|
|
789
|
-
},
|
|
790
|
-
emphasis: {
|
|
791
|
-
title: "Emphasis",
|
|
792
|
-
description: "Adds emphasis to the enclosed text.",
|
|
793
|
-
parameters: {
|
|
794
|
-
level: { title: "level", description: "Controls the amount of emphasis." }
|
|
795
|
-
}
|
|
796
|
-
},
|
|
797
|
-
audio: {
|
|
798
|
-
title: "Audio",
|
|
799
|
-
description: "Plays an audio file as part of the synthesized output.",
|
|
800
|
-
parameters: {
|
|
801
|
-
src: { title: "src", description: "The URI of the audio file." },
|
|
802
|
-
desc: { title: "desc", description: "Alternative text to use if the audio cannot be played." },
|
|
803
|
-
clipBegin: { title: "clipBegin", description: "The starting offset within the audio file." },
|
|
804
|
-
clipEnd: { title: "clipEnd", description: "The ending offset within the audio file." },
|
|
805
|
-
speed: { title: "speed", description: "The playback speed of the audio file." },
|
|
806
|
-
repeatCount: { title: "repeatCount", description: "The number of times to repeat the audio." },
|
|
807
|
-
repeatDuration: {
|
|
808
|
-
title: "repeatDuration",
|
|
809
|
-
description: "The total duration for which the audio may repeat."
|
|
810
|
-
},
|
|
811
|
-
soundLevel: { title: "soundLevel", description: "The audio volume adjustment in decibels." }
|
|
812
|
-
}
|
|
813
|
-
},
|
|
814
|
-
sub: {
|
|
815
|
-
title: "Substitution",
|
|
816
|
-
description: "Substitutes the alias text when speaking the enclosed text.",
|
|
817
|
-
parameters: {
|
|
818
|
-
alias: { title: "alias", description: "The text to speak instead of the enclosed text." }
|
|
819
|
-
}
|
|
820
|
-
},
|
|
821
|
-
lang: {
|
|
822
|
-
title: "Language",
|
|
823
|
-
description: "Changes the language used for the enclosed text.",
|
|
824
|
-
parameters: {
|
|
825
|
-
"xml:lang": { title: "xml:lang", description: "The BCP-47 language tag." }
|
|
826
|
-
}
|
|
827
|
-
},
|
|
828
|
-
mark: {
|
|
829
|
-
title: "Mark",
|
|
830
|
-
description: "Inserts a custom marker into the synthesized audio stream.",
|
|
831
|
-
parameters: {
|
|
832
|
-
name: { title: "name", description: "The application-defined marker name." }
|
|
833
|
-
}
|
|
834
|
-
},
|
|
835
|
-
bookmark: {
|
|
836
|
-
title: "Bookmark",
|
|
837
|
-
description: "Inserts a bookmark marker into the synthesized audio stream.",
|
|
838
|
-
parameters: {
|
|
839
|
-
mark: { title: "mark", description: "The application-defined bookmark name." }
|
|
840
|
-
}
|
|
841
|
-
},
|
|
842
|
-
lexicon: {
|
|
843
|
-
title: "Lexicon",
|
|
844
|
-
description: "Associates a pronunciation lexicon with the synthesized document.",
|
|
845
|
-
parameters: {
|
|
846
|
-
uri: { title: "uri", description: "The URI of the pronunciation lexicon." }
|
|
847
|
-
}
|
|
848
|
-
},
|
|
849
|
-
p: { title: "Paragraph", description: "Groups text into a paragraph.", parameters: {} },
|
|
850
|
-
s: { title: "Sentence", description: "Groups text into a sentence.", parameters: {} },
|
|
851
|
-
w: { title: "Word", description: "Groups text into a word.", parameters: {} },
|
|
852
|
-
"mstts:silence": {
|
|
853
|
-
title: "Silence",
|
|
854
|
-
description: "Adds a specified silence before or after text or at a punctuation boundary.",
|
|
855
|
-
parameters: {
|
|
856
|
-
type: { title: "type", description: "The silence position or punctuation boundary." },
|
|
857
|
-
value: { title: "value", description: "The silence duration, for example `300ms`." }
|
|
858
|
-
}
|
|
859
|
-
},
|
|
860
|
-
"mstts:viseme": {
|
|
861
|
-
title: "Viseme",
|
|
862
|
-
description: "Requests viseme events for the synthesized audio.",
|
|
863
|
-
parameters: {
|
|
864
|
-
type: { title: "type", description: "The viseme event format." }
|
|
865
|
-
}
|
|
866
|
-
}
|
|
867
|
-
}
|
|
868
|
-
}
|
|
869
|
-
};
|
|
870
|
-
|
|
871
|
-
// packages/ssml-editor-react/src/constants/ui.ts
|
|
872
|
-
var DEFAULT_LOCALE = "ja";
|
|
873
|
-
var OVERLAY_Z_INDEX = 9999;
|
|
874
|
-
var SELECTION_OVERLAY_ABOVE_THRESHOLD_LINES = 4;
|
|
875
|
-
var SSML_INSERTION_MODES = {
|
|
876
|
-
insert: "insert",
|
|
877
|
-
wrap: "wrap"
|
|
878
|
-
};
|
|
879
|
-
|
|
880
57
|
// packages/ssml-editor-react/src/components/popovers/InsertionPopover.tsx
|
|
881
58
|
import { createPortal } from "react-dom";
|
|
882
59
|
|
|
@@ -954,6 +131,10 @@ var editorStyles = {
|
|
|
954
131
|
font: "inherit",
|
|
955
132
|
cursor: "pointer"
|
|
956
133
|
},
|
|
134
|
+
toolbarButtonActive: {
|
|
135
|
+
border: "1px solid var(--ssml-editor-active-border)",
|
|
136
|
+
backgroundColor: "var(--ssml-editor-active-bg)"
|
|
137
|
+
},
|
|
957
138
|
display: {
|
|
958
139
|
display: "grid",
|
|
959
140
|
gap: "0.5rem"
|
|
@@ -999,12 +180,35 @@ var editorStyles = {
|
|
|
999
180
|
whiteSpace: "nowrap",
|
|
1000
181
|
cursor: "pointer"
|
|
1001
182
|
},
|
|
183
|
+
toolbarOptionGroup: {
|
|
184
|
+
display: "grid",
|
|
185
|
+
gap: "0.125rem",
|
|
186
|
+
margin: 0,
|
|
187
|
+
padding: 0,
|
|
188
|
+
border: 0
|
|
189
|
+
},
|
|
190
|
+
toolbarOptionGroupLabel: {
|
|
191
|
+
padding: "0.375rem 0.5rem 0.125rem",
|
|
192
|
+
color: "var(--ssml-editor-color)",
|
|
193
|
+
fontSize: "0.875rem",
|
|
194
|
+
fontWeight: 600,
|
|
195
|
+
whiteSpace: "nowrap"
|
|
196
|
+
},
|
|
1002
197
|
toolbarEmpty: {
|
|
1003
198
|
margin: 0,
|
|
1004
199
|
padding: "0.375rem 0.5rem",
|
|
1005
200
|
color: "var(--ssml-editor-color)",
|
|
1006
201
|
whiteSpace: "nowrap"
|
|
1007
202
|
},
|
|
203
|
+
toolbarEmptySelect: {
|
|
204
|
+
padding: "0.375rem 0.5rem",
|
|
205
|
+
border: "1px solid var(--ssml-editor-control-border)",
|
|
206
|
+
borderRadius: "0.125rem",
|
|
207
|
+
color: "var(--ssml-editor-color)",
|
|
208
|
+
backgroundColor: "var(--ssml-editor-control-bg)",
|
|
209
|
+
font: "inherit",
|
|
210
|
+
textAlign: "left"
|
|
211
|
+
},
|
|
1008
212
|
helpPanel: {
|
|
1009
213
|
display: "grid",
|
|
1010
214
|
gap: "0.5rem",
|
|
@@ -1130,1619 +334,175 @@ var editorStyles = {
|
|
|
1130
334
|
borderRadius: "0.25rem",
|
|
1131
335
|
color: "var(--ssml-editor-error)",
|
|
1132
336
|
backgroundColor: "var(--ssml-editor-error-bg)",
|
|
1133
|
-
lineHeight: 1.5
|
|
1134
|
-
}
|
|
1135
|
-
};
|
|
1136
|
-
|
|
1137
|
-
// packages/ssml-editor-react/src/components/popovers/InsertionPopover.tsx
|
|
1138
|
-
function getInsertionTitle(insertion, language) {
|
|
1139
|
-
if (insertion.titles) {
|
|
1140
|
-
return insertion.titles[language];
|
|
1141
|
-
}
|
|
1142
|
-
const tag = insertion.tagName ? ` <${insertion.tagName}${insertion.selfClosing ? "/>" : ">"}` : "";
|
|
1143
|
-
return `${insertion.labels[language]}${tag} \u2014 ${insertion.descriptions[language]}`;
|
|
1144
|
-
}
|
|
1145
|
-
function InsertionPopover({
|
|
1146
|
-
insertion,
|
|
1147
|
-
language,
|
|
1148
|
-
isDarkTheme,
|
|
1149
|
-
showToolbarIcons,
|
|
1150
|
-
showToolbarText,
|
|
1151
|
-
toolbarButtonStyle,
|
|
1152
|
-
emptyOptionsMessage,
|
|
1153
|
-
isReadOnly,
|
|
1154
|
-
isOpen,
|
|
1155
|
-
menuPosition,
|
|
1156
|
-
menuRef,
|
|
1157
|
-
onToggle,
|
|
1158
|
-
onClose,
|
|
1159
|
-
onApply
|
|
1160
|
-
}) {
|
|
1161
|
-
const menu = isOpen && menuPosition && typeof document !== "undefined" ? /* @__PURE__ */ React.createElement(
|
|
1162
|
-
"div",
|
|
1163
|
-
{
|
|
1164
|
-
ref: menuRef,
|
|
1165
|
-
id: `ssml-editor-popover-${insertion.id}`,
|
|
1166
|
-
"data-ssml-editor": "",
|
|
1167
|
-
"data-theme": isDarkTheme ? "dark" : "light",
|
|
1168
|
-
style: { ...editorStyles.toolbarMenu, top: menuPosition.top, left: menuPosition.left },
|
|
1169
|
-
role: "menu",
|
|
1170
|
-
"aria-label": insertion.labels[language]
|
|
1171
|
-
},
|
|
1172
|
-
insertion.options.length === 0 ? /* @__PURE__ */ React.createElement("p", { role: "status", style: editorStyles.toolbarEmpty }, emptyOptionsMessage) : insertion.options.map((option) => /* @__PURE__ */ React.createElement(
|
|
1173
|
-
"button",
|
|
1174
|
-
{
|
|
1175
|
-
key: option.value,
|
|
1176
|
-
type: "button",
|
|
1177
|
-
role: "menuitem",
|
|
1178
|
-
style: editorStyles.toolbarOption,
|
|
1179
|
-
title: option.descriptions?.[language] ?? insertion.descriptions[language],
|
|
1180
|
-
disabled: isReadOnly,
|
|
1181
|
-
onMouseDown: (event) => event.preventDefault(),
|
|
1182
|
-
onClick: () => {
|
|
1183
|
-
if (!isReadOnly) {
|
|
1184
|
-
onApply(insertion, option);
|
|
1185
|
-
}
|
|
1186
|
-
onClose();
|
|
1187
|
-
}
|
|
1188
|
-
},
|
|
1189
|
-
option.labels[language]
|
|
1190
|
-
))
|
|
1191
|
-
) : null;
|
|
1192
|
-
return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("div", { style: editorStyles.toolbarDropdown }, /* @__PURE__ */ React.createElement(
|
|
1193
|
-
"button",
|
|
1194
|
-
{
|
|
1195
|
-
type: "button",
|
|
1196
|
-
style: toolbarButtonStyle,
|
|
1197
|
-
title: getInsertionTitle(insertion, language),
|
|
1198
|
-
"aria-label": insertion.labels[language],
|
|
1199
|
-
"aria-haspopup": "menu",
|
|
1200
|
-
"aria-expanded": isOpen,
|
|
1201
|
-
"aria-controls": isOpen ? `ssml-editor-popover-${insertion.id}` : void 0,
|
|
1202
|
-
onClick: (event) => onToggle(event.currentTarget)
|
|
1203
|
-
},
|
|
1204
|
-
showToolbarIcons && /* @__PURE__ */ React.createElement("span", { style: editorStyles.toolbarIcon, "aria-hidden": "true" }, insertion.icon),
|
|
1205
|
-
showToolbarText && /* @__PURE__ */ React.createElement("span", null, insertion.labels[language]),
|
|
1206
|
-
/* @__PURE__ */ React.createElement("span", { style: editorStyles.toolbarChevron, "aria-hidden": "true" }, "\u25BE")
|
|
1207
|
-
)), menu && createPortal(menu, document.body));
|
|
1208
|
-
}
|
|
1209
|
-
|
|
1210
|
-
// packages/ssml-editor-react/src/components/popovers/InsertionPopovers.tsx
|
|
1211
|
-
function InsertionPopovers({
|
|
1212
|
-
insertions,
|
|
1213
|
-
openPopoverId,
|
|
1214
|
-
onToggle,
|
|
1215
|
-
...props
|
|
1216
|
-
}) {
|
|
1217
|
-
return /* @__PURE__ */ React.createElement(React.Fragment, null, insertions.map((insertion) => /* @__PURE__ */ React.createElement(
|
|
1218
|
-
InsertionPopover,
|
|
1219
|
-
{
|
|
1220
|
-
key: insertion.id,
|
|
1221
|
-
...props,
|
|
1222
|
-
insertion,
|
|
1223
|
-
isOpen: openPopoverId === insertion.id,
|
|
1224
|
-
onToggle: (trigger) => onToggle(insertion.id, trigger)
|
|
1225
|
-
}
|
|
1226
|
-
)));
|
|
1227
|
-
}
|
|
1228
|
-
|
|
1229
|
-
// packages/ssml-editor-react/src/components/popovers/ProsodyPopovers.tsx
|
|
1230
|
-
function ProsodyPopovers({ insertions, voiceName, ...props }) {
|
|
1231
|
-
const filteredInsertions = insertions.map((insertion) => {
|
|
1232
|
-
if (insertion.id !== "emotion" || insertion.tagName?.toLowerCase() !== "mstts:express-as") {
|
|
1233
|
-
return insertion;
|
|
1234
|
-
}
|
|
1235
|
-
const styles = new Set(
|
|
1236
|
-
resolveExpressAsStyles(
|
|
1237
|
-
voiceName,
|
|
1238
|
-
insertion.options.map((option) => option.value)
|
|
1239
|
-
)
|
|
1240
|
-
);
|
|
1241
|
-
return {
|
|
1242
|
-
...insertion,
|
|
1243
|
-
options: insertion.options.filter((option) => styles.has(option.value))
|
|
1244
|
-
};
|
|
1245
|
-
});
|
|
1246
|
-
return /* @__PURE__ */ React.createElement(InsertionPopovers, { ...props, insertions: filteredInsertions });
|
|
1247
|
-
}
|
|
1248
|
-
|
|
1249
|
-
// packages/ssml-editor-react/src/components/popovers/TextPopovers.tsx
|
|
1250
|
-
function TextPopovers(props) {
|
|
1251
|
-
return /* @__PURE__ */ React.createElement(InsertionPopovers, { ...props });
|
|
1252
|
-
}
|
|
1253
|
-
|
|
1254
|
-
// packages/ssml-editor-react/src/components/popovers/TimingPopovers.tsx
|
|
1255
|
-
function TimingPopovers(props) {
|
|
1256
|
-
return /* @__PURE__ */ React.createElement(InsertionPopovers, { ...props });
|
|
1257
|
-
}
|
|
1258
|
-
|
|
1259
|
-
// packages/ssml-editor-react/src/hooks/useSsmlEditorState.ts
|
|
1260
|
-
import { useCallback, useEffect, useId, useRef, useState } from "react";
|
|
1261
|
-
|
|
1262
|
-
// packages/ssml-core/dist/index.mjs
|
|
1263
|
-
var __typeError = (msg) => {
|
|
1264
|
-
throw TypeError(msg);
|
|
1265
|
-
};
|
|
1266
|
-
var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg);
|
|
1267
|
-
var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
|
|
1268
|
-
var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
|
|
1269
|
-
var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), setter ? setter.call(obj, value) : member.set(obj, value), value);
|
|
1270
|
-
var SYNTHESIS_NAMESPACE = "http://www.w3.org/2001/10/synthesis";
|
|
1271
|
-
var MSTTS_NAMESPACE = "http://www.w3.org/2001/mstts";
|
|
1272
|
-
var DEFAULT_SSML_VERSION = "1.0";
|
|
1273
|
-
var DEFAULT_SSML_LANGUAGE = "en-US";
|
|
1274
|
-
var MAX_NESTING_DEPTH = 1e3;
|
|
1275
|
-
var XML_NAME_PATTERN = /^[A-Za-z_][A-Za-z0-9_.:-]*$/;
|
|
1276
|
-
var MSTTS_TAG_PREFIX = "mstts:";
|
|
1277
|
-
var SSML_TAGS = {
|
|
1278
|
-
SPEAK: "speak",
|
|
1279
|
-
VOICE: "voice",
|
|
1280
|
-
PROSODY: "prosody",
|
|
1281
|
-
BREAK: "break",
|
|
1282
|
-
EXPRESS_AS: "express-as",
|
|
1283
|
-
EXPRESS_AS_CAMEL: "expressAs",
|
|
1284
|
-
MSTTS_EXPRESS_AS: "mstts:express-as",
|
|
1285
|
-
SAY_AS: "say-as",
|
|
1286
|
-
SAY_AS_CAMEL: "sayAs",
|
|
1287
|
-
PHONEME: "phoneme",
|
|
1288
|
-
EMPHASIS: "emphasis",
|
|
1289
|
-
AUDIO: "audio",
|
|
1290
|
-
SUB: "sub",
|
|
1291
|
-
LANG: "lang",
|
|
1292
|
-
MARK: "mark",
|
|
1293
|
-
BOOKMARK: "bookmark",
|
|
1294
|
-
LEXICON: "lexicon",
|
|
1295
|
-
PARAGRAPH: "p",
|
|
1296
|
-
SENTENCE: "s",
|
|
1297
|
-
WORD: "w",
|
|
1298
|
-
MSTTS_SILENCE: "mstts:silence",
|
|
1299
|
-
SILENCE: "silence",
|
|
1300
|
-
MSTTS_VISEME: "mstts:viseme",
|
|
1301
|
-
VISEME: "viseme"
|
|
1302
|
-
};
|
|
1303
|
-
var SSML_ATTRS = {
|
|
1304
|
-
VERSION: "version",
|
|
1305
|
-
XMLNS: "xmlns",
|
|
1306
|
-
XML_LANG: "xml:lang",
|
|
1307
|
-
LANG: "lang",
|
|
1308
|
-
MSTTS_XMLNS: "xmlns:mstts",
|
|
1309
|
-
NAME: "name",
|
|
1310
|
-
EFFECT: "effect",
|
|
1311
|
-
RATE: "rate",
|
|
1312
|
-
PITCH: "pitch",
|
|
1313
|
-
VOLUME: "volume",
|
|
1314
|
-
CONTOUR: "contour",
|
|
1315
|
-
RANGE: "range",
|
|
1316
|
-
TIME: "time",
|
|
1317
|
-
STRENGTH: "strength",
|
|
1318
|
-
STYLE: "style",
|
|
1319
|
-
STYLE_DEGREE: "styledegree",
|
|
1320
|
-
STYLE_DEGREE_CAMEL: "styleDegree",
|
|
1321
|
-
ROLE: "role",
|
|
1322
|
-
INTERPRET_AS: "interpret-as",
|
|
1323
|
-
FORMAT: "format",
|
|
1324
|
-
DETAIL: "detail",
|
|
1325
|
-
ALPHABET: "alphabet",
|
|
1326
|
-
PH: "ph",
|
|
1327
|
-
LEVEL: "level",
|
|
1328
|
-
SRC: "src",
|
|
1329
|
-
DESC: "desc",
|
|
1330
|
-
CLIP_BEGIN: "clipBegin",
|
|
1331
|
-
CLIP_END: "clipEnd",
|
|
1332
|
-
SPEED: "speed",
|
|
1333
|
-
REPEAT_COUNT: "repeatCount",
|
|
1334
|
-
REPEAT_DURATION: "repeatDuration",
|
|
1335
|
-
SOUND_LEVEL: "soundLevel",
|
|
1336
|
-
ALIAS: "alias",
|
|
1337
|
-
MARK: "mark",
|
|
1338
|
-
URI: "uri",
|
|
1339
|
-
TYPE: "type",
|
|
1340
|
-
VALUE: "value"
|
|
1341
|
-
};
|
|
1342
|
-
function escapeText(value) {
|
|
1343
|
-
return value.replace(/&/g, "&").replace(/</g, "<").replace(/>/g, ">");
|
|
1344
|
-
}
|
|
1345
|
-
function escapeAttribute(value) {
|
|
1346
|
-
return escapeText(value).replace(/"/g, """).replace(/'/g, "'");
|
|
1347
|
-
}
|
|
1348
|
-
function addAttribute(attributes, name, value) {
|
|
1349
|
-
if (value !== void 0) {
|
|
1350
|
-
attributes[name] = value;
|
|
1351
|
-
}
|
|
1352
|
-
}
|
|
1353
|
-
function getAttributes(element) {
|
|
1354
|
-
const attributes = {
|
|
1355
|
-
...element.attributes ?? {}
|
|
1356
|
-
};
|
|
1357
|
-
switch (element.type) {
|
|
1358
|
-
case SSML_TAGS.VOICE:
|
|
1359
|
-
addAttribute(attributes, SSML_ATTRS.NAME, element.name);
|
|
1360
|
-
addAttribute(attributes, SSML_ATTRS.EFFECT, element.effect);
|
|
1361
|
-
break;
|
|
1362
|
-
case SSML_TAGS.PROSODY:
|
|
1363
|
-
addAttribute(attributes, SSML_ATTRS.RATE, element.rate);
|
|
1364
|
-
addAttribute(attributes, SSML_ATTRS.PITCH, element.pitch);
|
|
1365
|
-
addAttribute(attributes, SSML_ATTRS.VOLUME, element.volume);
|
|
1366
|
-
addAttribute(attributes, SSML_ATTRS.CONTOUR, element.contour);
|
|
1367
|
-
addAttribute(attributes, SSML_ATTRS.RANGE, element.range);
|
|
1368
|
-
break;
|
|
1369
|
-
case SSML_TAGS.BREAK:
|
|
1370
|
-
addAttribute(attributes, SSML_ATTRS.TIME, element.time);
|
|
1371
|
-
addAttribute(attributes, SSML_ATTRS.STRENGTH, element.strength);
|
|
1372
|
-
break;
|
|
1373
|
-
case SSML_TAGS.EXPRESS_AS:
|
|
1374
|
-
case SSML_TAGS.EXPRESS_AS_CAMEL:
|
|
1375
|
-
case SSML_TAGS.MSTTS_EXPRESS_AS:
|
|
1376
|
-
addAttribute(attributes, SSML_ATTRS.STYLE, element.style);
|
|
1377
|
-
addAttribute(attributes, SSML_ATTRS.STYLE_DEGREE, element.styleDegree);
|
|
1378
|
-
addAttribute(attributes, SSML_ATTRS.ROLE, element.role);
|
|
1379
|
-
break;
|
|
1380
|
-
case SSML_TAGS.SAY_AS:
|
|
1381
|
-
case SSML_TAGS.SAY_AS_CAMEL:
|
|
1382
|
-
addAttribute(attributes, SSML_ATTRS.INTERPRET_AS, element.interpretAs);
|
|
1383
|
-
addAttribute(attributes, SSML_ATTRS.FORMAT, element.format);
|
|
1384
|
-
addAttribute(attributes, SSML_ATTRS.DETAIL, element.detail);
|
|
1385
|
-
break;
|
|
1386
|
-
case SSML_TAGS.PHONEME:
|
|
1387
|
-
addAttribute(attributes, SSML_ATTRS.ALPHABET, element.alphabet);
|
|
1388
|
-
addAttribute(attributes, SSML_ATTRS.PH, element.ph);
|
|
1389
|
-
break;
|
|
1390
|
-
case SSML_TAGS.EMPHASIS:
|
|
1391
|
-
addAttribute(attributes, SSML_ATTRS.LEVEL, element.level);
|
|
1392
|
-
break;
|
|
1393
|
-
case SSML_TAGS.AUDIO:
|
|
1394
|
-
addAttribute(attributes, SSML_ATTRS.SRC, element.src);
|
|
1395
|
-
addAttribute(attributes, SSML_ATTRS.DESC, element.desc);
|
|
1396
|
-
addAttribute(attributes, SSML_ATTRS.CLIP_BEGIN, element.clipBegin);
|
|
1397
|
-
addAttribute(attributes, SSML_ATTRS.CLIP_END, element.clipEnd);
|
|
1398
|
-
addAttribute(attributes, SSML_ATTRS.SPEED, element.speed);
|
|
1399
|
-
addAttribute(attributes, SSML_ATTRS.REPEAT_COUNT, element.repeatCount);
|
|
1400
|
-
addAttribute(attributes, SSML_ATTRS.REPEAT_DURATION, element.repeatDuration);
|
|
1401
|
-
addAttribute(attributes, SSML_ATTRS.SOUND_LEVEL, element.soundLevel);
|
|
1402
|
-
break;
|
|
1403
|
-
case SSML_TAGS.SUB:
|
|
1404
|
-
addAttribute(attributes, SSML_ATTRS.ALIAS, element.alias);
|
|
1405
|
-
break;
|
|
1406
|
-
case SSML_TAGS.LANG:
|
|
1407
|
-
addAttribute(attributes, SSML_ATTRS.XML_LANG, element.lang);
|
|
1408
|
-
break;
|
|
1409
|
-
case SSML_TAGS.MARK:
|
|
1410
|
-
addAttribute(attributes, SSML_ATTRS.NAME, element.name);
|
|
1411
|
-
break;
|
|
1412
|
-
case SSML_TAGS.BOOKMARK:
|
|
1413
|
-
addAttribute(attributes, SSML_ATTRS.MARK, element.mark);
|
|
1414
|
-
break;
|
|
1415
|
-
case SSML_TAGS.LEXICON:
|
|
1416
|
-
addAttribute(attributes, SSML_ATTRS.URI, element.uri);
|
|
1417
|
-
break;
|
|
1418
|
-
case SSML_TAGS.MSTTS_SILENCE:
|
|
1419
|
-
case SSML_TAGS.SILENCE:
|
|
1420
|
-
addAttribute(attributes, SSML_ATTRS.TYPE, element.typeValue ?? element.silenceType);
|
|
1421
|
-
addAttribute(attributes, SSML_ATTRS.VALUE, element.value);
|
|
1422
|
-
break;
|
|
1423
|
-
case SSML_TAGS.MSTTS_VISEME:
|
|
1424
|
-
case SSML_TAGS.VISEME:
|
|
1425
|
-
addAttribute(attributes, SSML_ATTRS.TYPE, element.typeValue ?? element.visemeType);
|
|
1426
|
-
break;
|
|
1427
|
-
case SSML_TAGS.PARAGRAPH:
|
|
1428
|
-
case SSML_TAGS.SENTENCE:
|
|
1429
|
-
case SSML_TAGS.WORD:
|
|
1430
|
-
case "element":
|
|
1431
|
-
case "custom":
|
|
1432
|
-
break;
|
|
1433
|
-
}
|
|
1434
|
-
return attributes;
|
|
1435
|
-
}
|
|
1436
|
-
function getTagName(element) {
|
|
1437
|
-
switch (element.type) {
|
|
1438
|
-
case SSML_TAGS.EXPRESS_AS:
|
|
1439
|
-
case SSML_TAGS.EXPRESS_AS_CAMEL:
|
|
1440
|
-
case SSML_TAGS.MSTTS_EXPRESS_AS:
|
|
1441
|
-
return SSML_TAGS.MSTTS_EXPRESS_AS;
|
|
1442
|
-
case SSML_TAGS.SAY_AS:
|
|
1443
|
-
case SSML_TAGS.SAY_AS_CAMEL:
|
|
1444
|
-
return SSML_TAGS.SAY_AS;
|
|
1445
|
-
case SSML_TAGS.SILENCE:
|
|
1446
|
-
case SSML_TAGS.MSTTS_SILENCE:
|
|
1447
|
-
return SSML_TAGS.MSTTS_SILENCE;
|
|
1448
|
-
case SSML_TAGS.VISEME:
|
|
1449
|
-
case SSML_TAGS.MSTTS_VISEME:
|
|
1450
|
-
return SSML_TAGS.MSTTS_VISEME;
|
|
1451
|
-
case "element":
|
|
1452
|
-
case "custom":
|
|
1453
|
-
return element.name;
|
|
1454
|
-
default:
|
|
1455
|
-
return element.type;
|
|
1456
|
-
}
|
|
1457
|
-
}
|
|
1458
|
-
function getChildren(element) {
|
|
1459
|
-
return element.children ?? [];
|
|
1460
|
-
}
|
|
1461
|
-
function validateName(name, kind) {
|
|
1462
|
-
if (!XML_NAME_PATTERN.test(name)) {
|
|
1463
|
-
throw new Error(`Invalid XML ${kind} name: ${name}`);
|
|
1464
|
-
}
|
|
1465
|
-
}
|
|
1466
|
-
function serializeAttributes(attributes) {
|
|
1467
|
-
return Object.entries(attributes).map(([name, value]) => {
|
|
1468
|
-
validateName(name, "attribute");
|
|
1469
|
-
return ` ${name}="${escapeAttribute(String(value))}"`;
|
|
1470
|
-
}).join("");
|
|
1471
|
-
}
|
|
1472
|
-
function serializeNode(node) {
|
|
1473
|
-
if (typeof node === "string") {
|
|
1474
|
-
return escapeText(node);
|
|
1475
|
-
}
|
|
1476
|
-
if (node.type === "text") {
|
|
1477
|
-
return escapeText(node.value);
|
|
1478
|
-
}
|
|
1479
|
-
const tagName = getTagName(node);
|
|
1480
|
-
validateName(tagName, "element");
|
|
1481
|
-
const attributes = serializeAttributes(getAttributes(node));
|
|
1482
|
-
const children = getChildren(node);
|
|
1483
|
-
if (children.length === 0) {
|
|
1484
|
-
return `<${tagName}${attributes}/>`;
|
|
1485
|
-
}
|
|
1486
|
-
return `<${tagName}${attributes}>${children.map(serializeNode).join("")}</${tagName}>`;
|
|
1487
|
-
}
|
|
1488
|
-
function usesMsttsNamespace(nodes) {
|
|
1489
|
-
return nodes.some((node) => {
|
|
1490
|
-
if (typeof node === "string" || node.type === "text") {
|
|
1491
|
-
return false;
|
|
1492
|
-
}
|
|
1493
|
-
const tagName = getTagName(node);
|
|
1494
|
-
return tagName.startsWith(MSTTS_TAG_PREFIX) || usesMsttsNamespace(getChildren(node));
|
|
1495
|
-
});
|
|
1496
|
-
}
|
|
1497
|
-
function serializeDocument(document2) {
|
|
1498
|
-
const children = document2.children ?? (document2.content === void 0 ? [] : [document2.content]);
|
|
1499
|
-
const attributes = {
|
|
1500
|
-
...document2.attributes ?? {},
|
|
1501
|
-
[SSML_ATTRS.VERSION]: document2.version,
|
|
1502
|
-
[SSML_ATTRS.XMLNS]: SYNTHESIS_NAMESPACE,
|
|
1503
|
-
[SSML_ATTRS.XML_LANG]: document2.lang
|
|
1504
|
-
};
|
|
1505
|
-
if (usesMsttsNamespace(children) && attributes[SSML_ATTRS.MSTTS_XMLNS] === void 0) {
|
|
1506
|
-
attributes[SSML_ATTRS.MSTTS_XMLNS] = MSTTS_NAMESPACE;
|
|
1507
|
-
}
|
|
1508
|
-
return `<${SSML_TAGS.SPEAK}${serializeAttributes(attributes)}>${children.map(serializeNode).join("")}</${SSML_TAGS.SPEAK}>`;
|
|
1509
|
-
}
|
|
1510
|
-
function buildSsml(documentOrContent, lang = DEFAULT_SSML_LANGUAGE) {
|
|
1511
|
-
if (typeof documentOrContent === "string") {
|
|
1512
|
-
return {
|
|
1513
|
-
version: DEFAULT_SSML_VERSION,
|
|
1514
|
-
lang,
|
|
1515
|
-
content: documentOrContent
|
|
1516
|
-
};
|
|
1517
|
-
}
|
|
1518
|
-
return serializeDocument(documentOrContent);
|
|
1519
|
-
}
|
|
1520
|
-
var XML_ENTITIES = {
|
|
1521
|
-
amp: "&",
|
|
1522
|
-
apos: "'",
|
|
1523
|
-
gt: ">",
|
|
1524
|
-
lt: "<",
|
|
1525
|
-
quot: '"'
|
|
1526
|
-
};
|
|
1527
|
-
function hasOwn(object, property) {
|
|
1528
|
-
return Object.getOwnPropertyDescriptor(object, property) !== void 0;
|
|
1529
|
-
}
|
|
1530
|
-
function setAttribute(attributes, name, value) {
|
|
1531
|
-
Object.defineProperty(attributes, name, {
|
|
1532
|
-
configurable: true,
|
|
1533
|
-
enumerable: true,
|
|
1534
|
-
value,
|
|
1535
|
-
writable: true
|
|
1536
|
-
});
|
|
1537
|
-
}
|
|
1538
|
-
function decodeEntity(entity) {
|
|
1539
|
-
const namedValue = hasOwn(XML_ENTITIES, entity) ? XML_ENTITIES[entity] : void 0;
|
|
1540
|
-
if (namedValue !== void 0) {
|
|
1541
|
-
return namedValue;
|
|
1542
|
-
}
|
|
1543
|
-
const isHexadecimal = entity.startsWith("#x") || entity.startsWith("#X");
|
|
1544
|
-
const isDecimal = entity.startsWith("#");
|
|
1545
|
-
if (!isHexadecimal && !isDecimal) {
|
|
1546
|
-
throw new Error(`Unknown XML entity: &${entity};`);
|
|
1547
|
-
}
|
|
1548
|
-
const digits = entity.slice(isHexadecimal ? 2 : 1);
|
|
1549
|
-
const codePoint = Number.parseInt(digits, isHexadecimal ? 16 : 10);
|
|
1550
|
-
if (!digits || !Number.isInteger(codePoint) || codePoint < 0 || codePoint > 1114111 || codePoint >= 55296 && codePoint <= 57343 || codePoint < 32 && ![9, 10, 13].includes(codePoint)) {
|
|
1551
|
-
throw new Error(`Invalid XML character reference: &${entity};`);
|
|
1552
|
-
}
|
|
1553
|
-
return String.fromCodePoint(codePoint);
|
|
1554
|
-
}
|
|
1555
|
-
function decodeXmlEntities(value) {
|
|
1556
|
-
let result = "";
|
|
1557
|
-
let start = 0;
|
|
1558
|
-
while (true) {
|
|
1559
|
-
const ampersand = value.indexOf("&", start);
|
|
1560
|
-
if (ampersand === -1) {
|
|
1561
|
-
return result + value.slice(start);
|
|
1562
|
-
}
|
|
1563
|
-
result += value.slice(start, ampersand);
|
|
1564
|
-
const semicolon = value.indexOf(";", ampersand + 1);
|
|
1565
|
-
if (semicolon === -1) {
|
|
1566
|
-
throw new Error("Unterminated XML entity reference");
|
|
1567
|
-
}
|
|
1568
|
-
result += decodeEntity(value.slice(ampersand + 1, semicolon));
|
|
1569
|
-
start = semicolon + 1;
|
|
1570
|
-
}
|
|
1571
|
-
}
|
|
1572
|
-
function isXmlNameStart(value) {
|
|
1573
|
-
return value !== void 0 && /[A-Za-z_]/.test(value);
|
|
1574
|
-
}
|
|
1575
|
-
function isXmlNameCharacter(value) {
|
|
1576
|
-
return value !== void 0 && /[A-Za-z0-9_.:-]/.test(value);
|
|
1577
|
-
}
|
|
1578
|
-
function isXmlWhitespace(value) {
|
|
1579
|
-
return value === " " || value === " " || value === "\r" || value === "\n";
|
|
1580
|
-
}
|
|
1581
|
-
function removeStandardNamespaceAttributes(attributes) {
|
|
1582
|
-
if (attributes[SSML_ATTRS.XMLNS] === SYNTHESIS_NAMESPACE) {
|
|
1583
|
-
delete attributes[SSML_ATTRS.XMLNS];
|
|
1584
|
-
}
|
|
1585
|
-
if (attributes[SSML_ATTRS.MSTTS_XMLNS] === MSTTS_NAMESPACE) {
|
|
1586
|
-
delete attributes[SSML_ATTRS.MSTTS_XMLNS];
|
|
1587
|
-
}
|
|
1588
|
-
}
|
|
1589
|
-
var _index;
|
|
1590
|
-
var XmlParser = class {
|
|
1591
|
-
constructor(source) {
|
|
1592
|
-
__privateAdd(this, _index, 0);
|
|
1593
|
-
this.source = source;
|
|
1594
|
-
}
|
|
1595
|
-
parse() {
|
|
1596
|
-
if (this.source.charCodeAt(0) === 65279) {
|
|
1597
|
-
__privateSet(this, _index, __privateGet(this, _index) + 1);
|
|
1598
|
-
}
|
|
1599
|
-
this.skipMisc();
|
|
1600
|
-
if (__privateGet(this, _index) >= this.source.length) {
|
|
1601
|
-
this.fail("SSML input is empty");
|
|
1602
|
-
}
|
|
1603
|
-
if (this.source[__privateGet(this, _index)] !== "<") {
|
|
1604
|
-
this.fail("SSML input must start with an XML element");
|
|
1605
|
-
}
|
|
1606
|
-
const root = this.parseElement(0);
|
|
1607
|
-
this.skipMisc();
|
|
1608
|
-
if (__privateGet(this, _index) !== this.source.length) {
|
|
1609
|
-
this.fail("Unexpected content after the root XML element");
|
|
1610
|
-
}
|
|
1611
|
-
return root;
|
|
1612
|
-
}
|
|
1613
|
-
parseElement(depth) {
|
|
1614
|
-
if (depth > MAX_NESTING_DEPTH) {
|
|
1615
|
-
this.fail("XML nesting depth exceeds the supported limit");
|
|
1616
|
-
}
|
|
1617
|
-
this.expect("<");
|
|
1618
|
-
if (this.source[__privateGet(this, _index)] === "/") {
|
|
1619
|
-
this.fail("Unexpected closing XML element");
|
|
1620
|
-
}
|
|
1621
|
-
const name = this.parseName();
|
|
1622
|
-
const { attributes, selfClosing } = this.parseStartTag();
|
|
1623
|
-
if (selfClosing) {
|
|
1624
|
-
return { name, attributes, children: [] };
|
|
1625
|
-
}
|
|
1626
|
-
const children = [];
|
|
1627
|
-
while (__privateGet(this, _index) < this.source.length) {
|
|
1628
|
-
if (this.source.startsWith("</", __privateGet(this, _index))) {
|
|
1629
|
-
__privateSet(this, _index, __privateGet(this, _index) + 2);
|
|
1630
|
-
const closingName = this.parseName();
|
|
1631
|
-
this.skipWhitespace();
|
|
1632
|
-
this.expect(">");
|
|
1633
|
-
if (closingName !== name) {
|
|
1634
|
-
this.fail(`Mismatched closing element: expected </${name}> but found </${closingName}>`);
|
|
1635
|
-
}
|
|
1636
|
-
return { name, attributes, children };
|
|
1637
|
-
}
|
|
1638
|
-
if (this.source.startsWith("<!--", __privateGet(this, _index))) {
|
|
1639
|
-
this.skipComment();
|
|
1640
|
-
continue;
|
|
1641
|
-
}
|
|
1642
|
-
if (this.source.startsWith("<![CDATA[", __privateGet(this, _index))) {
|
|
1643
|
-
this.appendText(children, this.parseCdata());
|
|
1644
|
-
continue;
|
|
1645
|
-
}
|
|
1646
|
-
if (this.source.startsWith("<?", __privateGet(this, _index))) {
|
|
1647
|
-
this.skipProcessingInstruction();
|
|
1648
|
-
continue;
|
|
1649
|
-
}
|
|
1650
|
-
if (this.source.startsWith("<!", __privateGet(this, _index))) {
|
|
1651
|
-
this.fail("Unsupported XML declaration inside an element");
|
|
1652
|
-
}
|
|
1653
|
-
if (this.source[__privateGet(this, _index)] === "<") {
|
|
1654
|
-
children.push(this.parseElement(depth + 1));
|
|
1655
|
-
} else {
|
|
1656
|
-
this.appendText(children, this.parseText());
|
|
1657
|
-
}
|
|
1658
|
-
}
|
|
1659
|
-
this.fail(`Unclosed XML element: <${name}>`);
|
|
1660
|
-
}
|
|
1661
|
-
parseStartTag() {
|
|
1662
|
-
const attributes = {};
|
|
1663
|
-
while (__privateGet(this, _index) < this.source.length) {
|
|
1664
|
-
this.skipWhitespace();
|
|
1665
|
-
if (this.source.startsWith("/>", __privateGet(this, _index))) {
|
|
1666
|
-
__privateSet(this, _index, __privateGet(this, _index) + 2);
|
|
1667
|
-
return { attributes, selfClosing: true };
|
|
1668
|
-
}
|
|
1669
|
-
if (this.source[__privateGet(this, _index)] === ">") {
|
|
1670
|
-
__privateSet(this, _index, __privateGet(this, _index) + 1);
|
|
1671
|
-
return { attributes, selfClosing: false };
|
|
1672
|
-
}
|
|
1673
|
-
const name = this.parseName();
|
|
1674
|
-
this.skipWhitespace();
|
|
1675
|
-
this.expect("=");
|
|
1676
|
-
this.skipWhitespace();
|
|
1677
|
-
const quote = this.source[__privateGet(this, _index)];
|
|
1678
|
-
if (quote !== '"' && quote !== "'") {
|
|
1679
|
-
this.fail(`XML attribute ${name} must use a quoted value`);
|
|
1680
|
-
}
|
|
1681
|
-
__privateSet(this, _index, __privateGet(this, _index) + 1);
|
|
1682
|
-
const valueStart = __privateGet(this, _index);
|
|
1683
|
-
while (__privateGet(this, _index) < this.source.length && this.source[__privateGet(this, _index)] !== quote) {
|
|
1684
|
-
if (this.source[__privateGet(this, _index)] === "<") {
|
|
1685
|
-
this.fail(`Invalid "<" in XML attribute ${name}`);
|
|
1686
|
-
}
|
|
1687
|
-
__privateSet(this, _index, __privateGet(this, _index) + 1);
|
|
1688
|
-
}
|
|
1689
|
-
if (__privateGet(this, _index) >= this.source.length) {
|
|
1690
|
-
this.fail(`Unclosed XML attribute ${name}`);
|
|
1691
|
-
}
|
|
1692
|
-
const value = decodeXmlEntities(this.source.slice(valueStart, __privateGet(this, _index)));
|
|
1693
|
-
__privateSet(this, _index, __privateGet(this, _index) + 1);
|
|
1694
|
-
if (hasOwn(attributes, name)) {
|
|
1695
|
-
this.fail(`Duplicate XML attribute: ${name}`);
|
|
1696
|
-
}
|
|
1697
|
-
setAttribute(attributes, name, value);
|
|
1698
|
-
}
|
|
1699
|
-
this.fail("Unclosed XML start tag");
|
|
1700
|
-
}
|
|
1701
|
-
parseText() {
|
|
1702
|
-
const start = __privateGet(this, _index);
|
|
1703
|
-
while (__privateGet(this, _index) < this.source.length && this.source[__privateGet(this, _index)] !== "<") {
|
|
1704
|
-
__privateSet(this, _index, __privateGet(this, _index) + 1);
|
|
1705
|
-
}
|
|
1706
|
-
const value = this.source.slice(start, __privateGet(this, _index));
|
|
1707
|
-
if (value.includes("]]>")) {
|
|
1708
|
-
this.fail("CDATA termination is not valid in ordinary XML text");
|
|
1709
|
-
}
|
|
1710
|
-
return decodeXmlEntities(value);
|
|
1711
|
-
}
|
|
1712
|
-
parseCdata() {
|
|
1713
|
-
__privateSet(this, _index, __privateGet(this, _index) + "<![CDATA[".length);
|
|
1714
|
-
const end = this.source.indexOf("]]>", __privateGet(this, _index));
|
|
1715
|
-
if (end === -1) {
|
|
1716
|
-
this.fail("Unclosed XML CDATA section");
|
|
1717
|
-
}
|
|
1718
|
-
const value = this.source.slice(__privateGet(this, _index), end);
|
|
1719
|
-
__privateSet(this, _index, end + 3);
|
|
1720
|
-
return value;
|
|
1721
|
-
}
|
|
1722
|
-
skipComment() {
|
|
1723
|
-
__privateSet(this, _index, __privateGet(this, _index) + "<!--".length);
|
|
1724
|
-
const end = this.source.indexOf("-->", __privateGet(this, _index));
|
|
1725
|
-
if (end === -1) {
|
|
1726
|
-
this.fail("Unclosed XML comment");
|
|
1727
|
-
}
|
|
1728
|
-
if (this.source.slice(__privateGet(this, _index), end).includes("--")) {
|
|
1729
|
-
this.fail("XML comments cannot contain consecutive hyphens");
|
|
1730
|
-
}
|
|
1731
|
-
__privateSet(this, _index, end + 3);
|
|
1732
|
-
}
|
|
1733
|
-
skipProcessingInstruction() {
|
|
1734
|
-
__privateSet(this, _index, __privateGet(this, _index) + "<?".length);
|
|
1735
|
-
this.parseName();
|
|
1736
|
-
const end = this.source.indexOf("?>", __privateGet(this, _index));
|
|
1737
|
-
if (end === -1) {
|
|
1738
|
-
this.fail("Unclosed XML processing instruction");
|
|
1739
|
-
}
|
|
1740
|
-
__privateSet(this, _index, end + 2);
|
|
1741
|
-
}
|
|
1742
|
-
skipMisc() {
|
|
1743
|
-
while (__privateGet(this, _index) < this.source.length) {
|
|
1744
|
-
this.skipWhitespace();
|
|
1745
|
-
if (this.source.startsWith("<!--", __privateGet(this, _index))) {
|
|
1746
|
-
this.skipComment();
|
|
1747
|
-
continue;
|
|
1748
|
-
}
|
|
1749
|
-
if (this.source.startsWith("<?", __privateGet(this, _index))) {
|
|
1750
|
-
this.skipProcessingInstruction();
|
|
1751
|
-
continue;
|
|
1752
|
-
}
|
|
1753
|
-
if (this.source.startsWith("<!DOCTYPE", __privateGet(this, _index))) {
|
|
1754
|
-
this.fail("DOCTYPE declarations are not supported");
|
|
1755
|
-
}
|
|
1756
|
-
break;
|
|
1757
|
-
}
|
|
1758
|
-
}
|
|
1759
|
-
parseName() {
|
|
1760
|
-
const first = this.source[__privateGet(this, _index)];
|
|
1761
|
-
if (!isXmlNameStart(first)) {
|
|
1762
|
-
this.fail("Invalid XML name");
|
|
1763
|
-
}
|
|
1764
|
-
const start = __privateGet(this, _index);
|
|
1765
|
-
__privateSet(this, _index, __privateGet(this, _index) + 1);
|
|
1766
|
-
while (isXmlNameCharacter(this.source[__privateGet(this, _index)])) {
|
|
1767
|
-
__privateSet(this, _index, __privateGet(this, _index) + 1);
|
|
1768
|
-
}
|
|
1769
|
-
return this.source.slice(start, __privateGet(this, _index));
|
|
1770
|
-
}
|
|
1771
|
-
appendText(children, value) {
|
|
1772
|
-
if (!value) {
|
|
1773
|
-
return;
|
|
1774
|
-
}
|
|
1775
|
-
const previous = children[children.length - 1];
|
|
1776
|
-
if (typeof previous === "string") {
|
|
1777
|
-
children[children.length - 1] = previous + value;
|
|
1778
|
-
} else {
|
|
1779
|
-
children.push(value);
|
|
1780
|
-
}
|
|
1781
|
-
}
|
|
1782
|
-
skipWhitespace() {
|
|
1783
|
-
while (isXmlWhitespace(this.source[__privateGet(this, _index)])) {
|
|
1784
|
-
__privateSet(this, _index, __privateGet(this, _index) + 1);
|
|
1785
|
-
}
|
|
1786
|
-
}
|
|
1787
|
-
expect(value) {
|
|
1788
|
-
if (!this.source.startsWith(value, __privateGet(this, _index))) {
|
|
1789
|
-
this.fail(`Expected "${value}"`);
|
|
1790
|
-
}
|
|
1791
|
-
__privateSet(this, _index, __privateGet(this, _index) + value.length);
|
|
1792
|
-
}
|
|
1793
|
-
fail(message) {
|
|
1794
|
-
throw new Error(`${message} at position ${__privateGet(this, _index)}`);
|
|
1795
|
-
}
|
|
1796
|
-
};
|
|
1797
|
-
_index = /* @__PURE__ */ new WeakMap();
|
|
1798
|
-
function readAttribute(attributes, ...names) {
|
|
1799
|
-
let found = false;
|
|
1800
|
-
let value;
|
|
1801
|
-
for (const name of names) {
|
|
1802
|
-
if (hasOwn(attributes, name)) {
|
|
1803
|
-
if (!found) {
|
|
1804
|
-
value = String(attributes[name]);
|
|
1805
|
-
found = true;
|
|
1806
|
-
}
|
|
1807
|
-
delete attributes[name];
|
|
1808
|
-
}
|
|
1809
|
-
}
|
|
1810
|
-
return value;
|
|
1811
|
-
}
|
|
1812
|
-
function getElementAttributes(node) {
|
|
1813
|
-
const attributes = { ...node.attributes };
|
|
1814
|
-
removeStandardNamespaceAttributes(attributes);
|
|
1815
|
-
return attributes;
|
|
1816
|
-
}
|
|
1817
|
-
function finishElement(element, node, attributes) {
|
|
1818
|
-
if (node.children.length > 0) {
|
|
1819
|
-
element.children = node.children.map(convertNode);
|
|
1820
|
-
}
|
|
1821
|
-
if (Object.keys(attributes).length > 0) {
|
|
1822
|
-
element.attributes = attributes;
|
|
1823
|
-
}
|
|
1824
|
-
return element;
|
|
1825
|
-
}
|
|
1826
|
-
function convertElement(node) {
|
|
1827
|
-
const attributes = getElementAttributes(node);
|
|
1828
|
-
switch (node.name) {
|
|
1829
|
-
case SSML_TAGS.VOICE: {
|
|
1830
|
-
const element = { type: SSML_TAGS.VOICE };
|
|
1831
|
-
const name = readAttribute(attributes, SSML_ATTRS.NAME);
|
|
1832
|
-
const effect = readAttribute(attributes, SSML_ATTRS.EFFECT);
|
|
1833
|
-
if (name !== void 0) element.name = name;
|
|
1834
|
-
if (effect !== void 0) element.effect = effect;
|
|
1835
|
-
return finishElement(element, node, attributes);
|
|
1836
|
-
}
|
|
1837
|
-
case SSML_TAGS.PROSODY: {
|
|
1838
|
-
const element = { type: SSML_TAGS.PROSODY };
|
|
1839
|
-
const rate = readAttribute(attributes, SSML_ATTRS.RATE);
|
|
1840
|
-
const pitch = readAttribute(attributes, SSML_ATTRS.PITCH);
|
|
1841
|
-
const volume = readAttribute(attributes, SSML_ATTRS.VOLUME);
|
|
1842
|
-
const contour = readAttribute(attributes, SSML_ATTRS.CONTOUR);
|
|
1843
|
-
const range = readAttribute(attributes, SSML_ATTRS.RANGE);
|
|
1844
|
-
if (rate !== void 0) element.rate = rate;
|
|
1845
|
-
if (pitch !== void 0) element.pitch = pitch;
|
|
1846
|
-
if (volume !== void 0) element.volume = volume;
|
|
1847
|
-
if (contour !== void 0) element.contour = contour;
|
|
1848
|
-
if (range !== void 0) element.range = range;
|
|
1849
|
-
return finishElement(element, node, attributes);
|
|
1850
|
-
}
|
|
1851
|
-
case SSML_TAGS.BREAK: {
|
|
1852
|
-
const element = { type: SSML_TAGS.BREAK };
|
|
1853
|
-
const time = readAttribute(attributes, SSML_ATTRS.TIME);
|
|
1854
|
-
const strength = readAttribute(attributes, SSML_ATTRS.STRENGTH);
|
|
1855
|
-
if (time !== void 0) element.time = time;
|
|
1856
|
-
if (strength !== void 0) element.strength = strength;
|
|
1857
|
-
return finishElement(element, node, attributes);
|
|
1858
|
-
}
|
|
1859
|
-
case SSML_TAGS.EXPRESS_AS:
|
|
1860
|
-
case SSML_TAGS.EXPRESS_AS_CAMEL:
|
|
1861
|
-
case SSML_TAGS.MSTTS_EXPRESS_AS: {
|
|
1862
|
-
const element = { type: node.name };
|
|
1863
|
-
const style = readAttribute(attributes, SSML_ATTRS.STYLE);
|
|
1864
|
-
const styleDegree = readAttribute(attributes, SSML_ATTRS.STYLE_DEGREE, SSML_ATTRS.STYLE_DEGREE_CAMEL);
|
|
1865
|
-
const role = readAttribute(attributes, SSML_ATTRS.ROLE);
|
|
1866
|
-
if (style !== void 0) element.style = style;
|
|
1867
|
-
if (styleDegree !== void 0) element.styleDegree = styleDegree;
|
|
1868
|
-
if (role !== void 0) element.role = role;
|
|
1869
|
-
return finishElement(element, node, attributes);
|
|
1870
|
-
}
|
|
1871
|
-
case SSML_TAGS.SAY_AS:
|
|
1872
|
-
case SSML_TAGS.SAY_AS_CAMEL: {
|
|
1873
|
-
const element = { type: node.name };
|
|
1874
|
-
const interpretAs = readAttribute(attributes, SSML_ATTRS.INTERPRET_AS);
|
|
1875
|
-
const format = readAttribute(attributes, SSML_ATTRS.FORMAT);
|
|
1876
|
-
const detail = readAttribute(attributes, SSML_ATTRS.DETAIL);
|
|
1877
|
-
if (interpretAs !== void 0) element.interpretAs = interpretAs;
|
|
1878
|
-
if (format !== void 0) element.format = format;
|
|
1879
|
-
if (detail !== void 0) element.detail = detail;
|
|
1880
|
-
return finishElement(element, node, attributes);
|
|
1881
|
-
}
|
|
1882
|
-
case SSML_TAGS.PHONEME: {
|
|
1883
|
-
const element = { type: SSML_TAGS.PHONEME };
|
|
1884
|
-
const alphabet = readAttribute(attributes, SSML_ATTRS.ALPHABET);
|
|
1885
|
-
const ph = readAttribute(attributes, SSML_ATTRS.PH);
|
|
1886
|
-
if (alphabet !== void 0) element.alphabet = alphabet;
|
|
1887
|
-
if (ph !== void 0) element.ph = ph;
|
|
1888
|
-
return finishElement(element, node, attributes);
|
|
1889
|
-
}
|
|
1890
|
-
case SSML_TAGS.EMPHASIS: {
|
|
1891
|
-
const element = { type: SSML_TAGS.EMPHASIS };
|
|
1892
|
-
const level = readAttribute(attributes, SSML_ATTRS.LEVEL);
|
|
1893
|
-
if (level !== void 0) element.level = level;
|
|
1894
|
-
return finishElement(element, node, attributes);
|
|
1895
|
-
}
|
|
1896
|
-
case SSML_TAGS.AUDIO: {
|
|
1897
|
-
const element = { type: SSML_TAGS.AUDIO };
|
|
1898
|
-
const src = readAttribute(attributes, SSML_ATTRS.SRC);
|
|
1899
|
-
const desc = readAttribute(attributes, SSML_ATTRS.DESC);
|
|
1900
|
-
const clipBegin = readAttribute(attributes, SSML_ATTRS.CLIP_BEGIN);
|
|
1901
|
-
const clipEnd = readAttribute(attributes, SSML_ATTRS.CLIP_END);
|
|
1902
|
-
const speed = readAttribute(attributes, SSML_ATTRS.SPEED);
|
|
1903
|
-
const repeatCount = readAttribute(attributes, SSML_ATTRS.REPEAT_COUNT);
|
|
1904
|
-
const repeatDuration = readAttribute(attributes, SSML_ATTRS.REPEAT_DURATION);
|
|
1905
|
-
const soundLevel = readAttribute(attributes, SSML_ATTRS.SOUND_LEVEL);
|
|
1906
|
-
if (src !== void 0) element.src = src;
|
|
1907
|
-
if (desc !== void 0) element.desc = desc;
|
|
1908
|
-
if (clipBegin !== void 0) element.clipBegin = clipBegin;
|
|
1909
|
-
if (clipEnd !== void 0) element.clipEnd = clipEnd;
|
|
1910
|
-
if (speed !== void 0) element.speed = speed;
|
|
1911
|
-
if (repeatCount !== void 0) element.repeatCount = repeatCount;
|
|
1912
|
-
if (repeatDuration !== void 0) element.repeatDuration = repeatDuration;
|
|
1913
|
-
if (soundLevel !== void 0) element.soundLevel = soundLevel;
|
|
1914
|
-
return finishElement(element, node, attributes);
|
|
1915
|
-
}
|
|
1916
|
-
case SSML_TAGS.SUB: {
|
|
1917
|
-
const element = { type: SSML_TAGS.SUB };
|
|
1918
|
-
const alias = readAttribute(attributes, SSML_ATTRS.ALIAS);
|
|
1919
|
-
if (alias !== void 0) element.alias = alias;
|
|
1920
|
-
return finishElement(element, node, attributes);
|
|
1921
|
-
}
|
|
1922
|
-
case SSML_TAGS.LANG: {
|
|
1923
|
-
const element = { type: SSML_TAGS.LANG };
|
|
1924
|
-
const lang = readAttribute(attributes, SSML_ATTRS.XML_LANG, SSML_ATTRS.LANG);
|
|
1925
|
-
if (lang !== void 0) element.lang = lang;
|
|
1926
|
-
return finishElement(element, node, attributes);
|
|
1927
|
-
}
|
|
1928
|
-
case SSML_TAGS.MARK: {
|
|
1929
|
-
const element = { type: SSML_TAGS.MARK };
|
|
1930
|
-
const name = readAttribute(attributes, SSML_ATTRS.NAME);
|
|
1931
|
-
if (name !== void 0) element.name = name;
|
|
1932
|
-
return finishElement(element, node, attributes);
|
|
1933
|
-
}
|
|
1934
|
-
case SSML_TAGS.BOOKMARK: {
|
|
1935
|
-
const element = { type: SSML_TAGS.BOOKMARK };
|
|
1936
|
-
const mark = readAttribute(attributes, SSML_ATTRS.MARK);
|
|
1937
|
-
if (mark !== void 0) element.mark = mark;
|
|
1938
|
-
return finishElement(element, node, attributes);
|
|
1939
|
-
}
|
|
1940
|
-
case SSML_TAGS.LEXICON: {
|
|
1941
|
-
const element = { type: SSML_TAGS.LEXICON };
|
|
1942
|
-
const uri = readAttribute(attributes, SSML_ATTRS.URI);
|
|
1943
|
-
if (uri !== void 0) element.uri = uri;
|
|
1944
|
-
return finishElement(element, node, attributes);
|
|
1945
|
-
}
|
|
1946
|
-
case SSML_TAGS.PARAGRAPH: {
|
|
1947
|
-
const element = { type: SSML_TAGS.PARAGRAPH };
|
|
1948
|
-
return finishElement(element, node, attributes);
|
|
1949
|
-
}
|
|
1950
|
-
case SSML_TAGS.SENTENCE: {
|
|
1951
|
-
const element = { type: SSML_TAGS.SENTENCE };
|
|
1952
|
-
return finishElement(element, node, attributes);
|
|
1953
|
-
}
|
|
1954
|
-
case SSML_TAGS.WORD: {
|
|
1955
|
-
const element = { type: SSML_TAGS.WORD };
|
|
1956
|
-
return finishElement(element, node, attributes);
|
|
1957
|
-
}
|
|
1958
|
-
case SSML_TAGS.MSTTS_SILENCE:
|
|
1959
|
-
case SSML_TAGS.SILENCE: {
|
|
1960
|
-
const element = {
|
|
1961
|
-
type: node.name === SSML_TAGS.MSTTS_SILENCE ? SSML_TAGS.MSTTS_SILENCE : SSML_TAGS.SILENCE
|
|
1962
|
-
};
|
|
1963
|
-
const typeValue = readAttribute(attributes, SSML_ATTRS.TYPE);
|
|
1964
|
-
const value = readAttribute(attributes, SSML_ATTRS.VALUE);
|
|
1965
|
-
if (typeValue !== void 0) element.typeValue = typeValue;
|
|
1966
|
-
if (value !== void 0) element.value = value;
|
|
1967
|
-
return finishElement(element, node, attributes);
|
|
1968
|
-
}
|
|
1969
|
-
case SSML_TAGS.MSTTS_VISEME:
|
|
1970
|
-
case SSML_TAGS.VISEME: {
|
|
1971
|
-
const element = {
|
|
1972
|
-
type: node.name === SSML_TAGS.MSTTS_VISEME ? SSML_TAGS.MSTTS_VISEME : SSML_TAGS.VISEME
|
|
1973
|
-
};
|
|
1974
|
-
const typeValue = readAttribute(attributes, SSML_ATTRS.TYPE);
|
|
1975
|
-
if (typeValue !== void 0) element.typeValue = typeValue;
|
|
1976
|
-
return finishElement(element, node, attributes);
|
|
1977
|
-
}
|
|
1978
|
-
default: {
|
|
1979
|
-
const element = {
|
|
1980
|
-
name: node.name,
|
|
1981
|
-
type: "custom"
|
|
1982
|
-
};
|
|
1983
|
-
return finishElement(element, node, attributes);
|
|
1984
|
-
}
|
|
1985
|
-
}
|
|
1986
|
-
}
|
|
1987
|
-
function convertNode(node) {
|
|
1988
|
-
return typeof node === "string" ? node : convertElement(node);
|
|
1989
|
-
}
|
|
1990
|
-
function parseSsml(xmlString) {
|
|
1991
|
-
if (typeof xmlString !== "string") {
|
|
1992
|
-
throw new TypeError("SSML input must be a string");
|
|
1993
|
-
}
|
|
1994
|
-
const root = new XmlParser(xmlString).parse();
|
|
1995
|
-
if (root.name !== SSML_TAGS.SPEAK) {
|
|
1996
|
-
throw new Error(`SSML root element must be <${SSML_TAGS.SPEAK}>, found <${root.name}>`);
|
|
1997
|
-
}
|
|
1998
|
-
const attributes = { ...root.attributes };
|
|
1999
|
-
const version = readAttribute(attributes, SSML_ATTRS.VERSION);
|
|
2000
|
-
const lang = readAttribute(attributes, SSML_ATTRS.XML_LANG, SSML_ATTRS.LANG);
|
|
2001
|
-
if (version === void 0) {
|
|
2002
|
-
throw new Error(`SSML <${SSML_TAGS.SPEAK}> element is missing the "${SSML_ATTRS.VERSION}" attribute`);
|
|
2003
|
-
}
|
|
2004
|
-
if (lang === void 0) {
|
|
2005
|
-
throw new Error(`SSML <${SSML_TAGS.SPEAK}> element is missing the "${SSML_ATTRS.XML_LANG}" attribute`);
|
|
2006
|
-
}
|
|
2007
|
-
removeStandardNamespaceAttributes(attributes);
|
|
2008
|
-
const document2 = {
|
|
2009
|
-
children: root.children.map(convertNode),
|
|
2010
|
-
lang,
|
|
2011
|
-
type: SSML_TAGS.SPEAK,
|
|
2012
|
-
version
|
|
2013
|
-
};
|
|
2014
|
-
if (Object.keys(attributes).length > 0) {
|
|
2015
|
-
document2.attributes = attributes;
|
|
2016
|
-
}
|
|
2017
|
-
return document2;
|
|
2018
|
-
}
|
|
2019
|
-
function escapeAttribute2(value) {
|
|
2020
|
-
return value.replace(/&/g, "&").replace(/"/g, """).replace(/</g, "<").replace(/>/g, ">").replace(/'/g, "'");
|
|
2021
|
-
}
|
|
2022
|
-
function getPartialTextNodes(text, version, lang) {
|
|
2023
|
-
if (!text.includes("<")) {
|
|
2024
|
-
return [text];
|
|
2025
|
-
}
|
|
2026
|
-
try {
|
|
2027
|
-
const openingTag = `<${SSML_TAGS.SPEAK} ${SSML_ATTRS.VERSION}="${escapeAttribute2(version)}" ${SSML_ATTRS.XMLNS}="${SYNTHESIS_NAMESPACE}" ${SSML_ATTRS.XML_LANG}="${escapeAttribute2(lang)}">`;
|
|
2028
|
-
return parseSsml(`${openingTag}${text}</${SSML_TAGS.SPEAK}>`).children ?? [];
|
|
2029
|
-
} catch {
|
|
2030
|
-
return [{ type: "text", value: text }];
|
|
2031
|
-
}
|
|
2032
|
-
}
|
|
2033
|
-
function getVoiceContext(context) {
|
|
2034
|
-
const voice = context.voice;
|
|
2035
|
-
if (typeof voice === "object" && voice !== null) {
|
|
2036
|
-
return voice;
|
|
2037
|
-
}
|
|
2038
|
-
if (context.voiceName === void 0 && context.voiceEffect === void 0 && typeof voice !== "string") {
|
|
2039
|
-
return void 0;
|
|
2040
|
-
}
|
|
2041
|
-
return {
|
|
2042
|
-
name: context.voiceName ?? voice,
|
|
2043
|
-
effect: context.voiceEffect
|
|
2044
|
-
};
|
|
2045
|
-
}
|
|
2046
|
-
function serializePartialSsml(text, context) {
|
|
2047
|
-
const version = context.version ?? DEFAULT_SSML_VERSION;
|
|
2048
|
-
const lang = context.lang ?? DEFAULT_SSML_LANGUAGE;
|
|
2049
|
-
let children = getPartialTextNodes(text, version, lang);
|
|
2050
|
-
if (context.prosody) {
|
|
2051
|
-
children = [
|
|
2052
|
-
{
|
|
2053
|
-
type: SSML_TAGS.PROSODY,
|
|
2054
|
-
...context.prosody,
|
|
2055
|
-
children
|
|
2056
|
-
}
|
|
2057
|
-
];
|
|
2058
|
-
}
|
|
2059
|
-
const voice = getVoiceContext(context);
|
|
2060
|
-
if (voice) {
|
|
2061
|
-
children = [
|
|
2062
|
-
{
|
|
2063
|
-
type: SSML_TAGS.VOICE,
|
|
2064
|
-
...voice,
|
|
2065
|
-
children
|
|
2066
|
-
}
|
|
2067
|
-
];
|
|
2068
|
-
}
|
|
2069
|
-
const document2 = {
|
|
2070
|
-
type: SSML_TAGS.SPEAK,
|
|
2071
|
-
version,
|
|
2072
|
-
lang,
|
|
2073
|
-
attributes: context.attributes,
|
|
2074
|
-
children
|
|
2075
|
-
};
|
|
2076
|
-
return buildSsml(document2);
|
|
2077
|
-
}
|
|
2078
|
-
function buildPartialSsml(textOrOptions, context) {
|
|
2079
|
-
if (typeof textOrOptions === "string") {
|
|
2080
|
-
return serializePartialSsml(textOrOptions, context ?? {});
|
|
2081
|
-
}
|
|
2082
|
-
return serializePartialSsml(textOrOptions.text, textOrOptions);
|
|
2083
|
-
}
|
|
2084
|
-
var PARSER_POSITION_SUFFIX = / at position (\d+)$/;
|
|
2085
|
-
function validateSsml(xmlString) {
|
|
2086
|
-
try {
|
|
2087
|
-
parseSsml(xmlString);
|
|
2088
|
-
return null;
|
|
2089
|
-
} catch (error) {
|
|
2090
|
-
const rawMessage = error instanceof Error ? error.message : String(error);
|
|
2091
|
-
const positionMatch = PARSER_POSITION_SUFFIX.exec(rawMessage);
|
|
2092
|
-
return {
|
|
2093
|
-
message: positionMatch ? rawMessage.slice(0, positionMatch.index) : rawMessage,
|
|
2094
|
-
position: positionMatch ? Number.parseInt(positionMatch[1], 10) : 0
|
|
2095
|
-
};
|
|
2096
|
-
}
|
|
2097
|
-
}
|
|
2098
|
-
|
|
2099
|
-
// packages/ssml-editor-react/src/clearSsmlDocument.ts
|
|
2100
|
-
function getDocumentChildren(document2) {
|
|
2101
|
-
return document2.children ?? (document2.content === void 0 ? [] : [document2.content]);
|
|
2102
|
-
}
|
|
2103
|
-
function appendNode(nodes, node) {
|
|
2104
|
-
if (typeof node === "string") {
|
|
2105
|
-
const lastNode = nodes[nodes.length - 1];
|
|
2106
|
-
if (typeof lastNode === "string") {
|
|
2107
|
-
nodes[nodes.length - 1] = lastNode + node;
|
|
2108
|
-
} else if (node !== "") {
|
|
2109
|
-
nodes.push(node);
|
|
2110
|
-
}
|
|
2111
|
-
return;
|
|
2112
|
-
}
|
|
2113
|
-
nodes.push(node);
|
|
2114
|
-
}
|
|
2115
|
-
function clearNodes(nodes) {
|
|
2116
|
-
const clearedNodes = [];
|
|
2117
|
-
for (const node of nodes) {
|
|
2118
|
-
if (typeof node === "string") {
|
|
2119
|
-
appendNode(clearedNodes, node);
|
|
2120
|
-
continue;
|
|
2121
|
-
}
|
|
2122
|
-
if (node.type === "text") {
|
|
2123
|
-
appendNode(clearedNodes, node.value);
|
|
2124
|
-
continue;
|
|
2125
|
-
}
|
|
2126
|
-
const children = clearNodes(node.children ?? []);
|
|
2127
|
-
if (node.type === "voice") {
|
|
2128
|
-
appendNode(clearedNodes, { ...node, children });
|
|
2129
|
-
continue;
|
|
2130
|
-
}
|
|
2131
|
-
for (const child of children) {
|
|
2132
|
-
appendNode(clearedNodes, child);
|
|
2133
|
-
}
|
|
2134
|
-
}
|
|
2135
|
-
return clearedNodes;
|
|
2136
|
-
}
|
|
2137
|
-
function clearSsmlDocument(document2) {
|
|
2138
|
-
const nextDocument = {
|
|
2139
|
-
...document2,
|
|
2140
|
-
children: clearNodes(getDocumentChildren(document2))
|
|
2141
|
-
};
|
|
2142
|
-
if (nextDocument.content !== void 0) {
|
|
2143
|
-
delete nextDocument.content;
|
|
2144
|
-
}
|
|
2145
|
-
return nextDocument;
|
|
2146
|
-
}
|
|
2147
|
-
|
|
2148
|
-
// packages/ssml-editor-react/src/formatXml.ts
|
|
2149
|
-
var INDENT = " ";
|
|
2150
|
-
var FRAGMENT_ROOT = "ssml-builder-fragment";
|
|
2151
|
-
var XML_ENTITY_NAMES = /* @__PURE__ */ new Set(["amp", "apos", "gt", "lt", "quot"]);
|
|
2152
|
-
var INTRINSICALLY_EMPTY_ELEMENTS = /* @__PURE__ */ new Set([
|
|
2153
|
-
"break",
|
|
2154
|
-
"bookmark",
|
|
2155
|
-
"lexicon",
|
|
2156
|
-
"mark",
|
|
2157
|
-
"mstts:silence",
|
|
2158
|
-
"mstts:viseme",
|
|
2159
|
-
"silence",
|
|
2160
|
-
"viseme"
|
|
2161
|
-
]);
|
|
2162
|
-
function isXmlNameStart2(value) {
|
|
2163
|
-
return value !== void 0 && /[A-Za-z_]/.test(value);
|
|
2164
|
-
}
|
|
2165
|
-
function isXmlNameCharacter2(value) {
|
|
2166
|
-
return value !== void 0 && /[A-Za-z0-9_.:-]/.test(value);
|
|
2167
|
-
}
|
|
2168
|
-
function isXmlWhitespace2(value) {
|
|
2169
|
-
return value === " " || value === " " || value === "\r" || value === "\n";
|
|
2170
|
-
}
|
|
2171
|
-
function fail(message) {
|
|
2172
|
-
throw new Error(message);
|
|
2173
|
-
}
|
|
2174
|
-
function skipWhitespace(source, index) {
|
|
2175
|
-
while (isXmlWhitespace2(source[index])) {
|
|
2176
|
-
index += 1;
|
|
2177
|
-
}
|
|
2178
|
-
return index;
|
|
2179
|
-
}
|
|
2180
|
-
function readName(source, start, end) {
|
|
2181
|
-
if (!isXmlNameStart2(source[start])) {
|
|
2182
|
-
fail("Invalid XML name");
|
|
2183
|
-
}
|
|
2184
|
-
let index = start + 1;
|
|
2185
|
-
while (index < end && isXmlNameCharacter2(source[index])) {
|
|
2186
|
-
index += 1;
|
|
2187
|
-
}
|
|
2188
|
-
return { name: source.slice(start, index), index };
|
|
2189
|
-
}
|
|
2190
|
-
function validateCharacterReference(entity) {
|
|
2191
|
-
const isHexadecimal = entity.startsWith("#x") || entity.startsWith("#X");
|
|
2192
|
-
const isDecimal = entity.startsWith("#");
|
|
2193
|
-
if (!isHexadecimal && !isDecimal) {
|
|
2194
|
-
if (!XML_ENTITY_NAMES.has(entity)) {
|
|
2195
|
-
fail(`Unknown XML entity: &${entity};`);
|
|
2196
|
-
}
|
|
2197
|
-
return;
|
|
2198
|
-
}
|
|
2199
|
-
const digits = entity.slice(isHexadecimal ? 2 : 1);
|
|
2200
|
-
const validDigits = isHexadecimal ? /^[0-9A-Fa-f]+$/.test(digits) : /^[0-9]+$/.test(digits);
|
|
2201
|
-
const codePoint = Number.parseInt(digits, isHexadecimal ? 16 : 10);
|
|
2202
|
-
if (!validDigits || !Number.isInteger(codePoint) || codePoint < 0 || codePoint > 1114111 || codePoint >= 55296 && codePoint <= 57343 || codePoint < 32 && ![9, 10, 13].includes(codePoint)) {
|
|
2203
|
-
fail(`Invalid XML character reference: &${entity};`);
|
|
2204
|
-
}
|
|
2205
|
-
}
|
|
2206
|
-
function validateEntityReferences(value) {
|
|
2207
|
-
let index = 0;
|
|
2208
|
-
while (true) {
|
|
2209
|
-
const ampersand = value.indexOf("&", index);
|
|
2210
|
-
if (ampersand === -1) {
|
|
2211
|
-
return;
|
|
2212
|
-
}
|
|
2213
|
-
const semicolon = value.indexOf(";", ampersand + 1);
|
|
2214
|
-
if (semicolon === -1) {
|
|
2215
|
-
fail("Unterminated XML entity reference");
|
|
2216
|
-
}
|
|
2217
|
-
validateCharacterReference(value.slice(ampersand + 1, semicolon));
|
|
2218
|
-
index = semicolon + 1;
|
|
2219
|
-
}
|
|
2220
|
-
}
|
|
2221
|
-
function findTagEnd(source, start, hasInternalSubset = false) {
|
|
2222
|
-
let quote;
|
|
2223
|
-
let subsetDepth = 0;
|
|
2224
|
-
for (let index = start + 1; index < source.length; index += 1) {
|
|
2225
|
-
const character = source[index];
|
|
2226
|
-
if (quote !== void 0) {
|
|
2227
|
-
if (character === quote) {
|
|
2228
|
-
quote = void 0;
|
|
2229
|
-
}
|
|
2230
|
-
continue;
|
|
2231
|
-
}
|
|
2232
|
-
if (character === '"' || character === "'") {
|
|
2233
|
-
quote = character;
|
|
2234
|
-
continue;
|
|
2235
|
-
}
|
|
2236
|
-
if (hasInternalSubset) {
|
|
2237
|
-
if (character === "[") {
|
|
2238
|
-
subsetDepth += 1;
|
|
2239
|
-
continue;
|
|
2240
|
-
}
|
|
2241
|
-
if (character === "]" && subsetDepth > 0) {
|
|
2242
|
-
subsetDepth -= 1;
|
|
2243
|
-
continue;
|
|
2244
|
-
}
|
|
2245
|
-
}
|
|
2246
|
-
if (character === ">" && subsetDepth === 0) {
|
|
2247
|
-
return index;
|
|
2248
|
-
}
|
|
2249
|
-
}
|
|
2250
|
-
fail("Unclosed XML markup");
|
|
2251
|
-
}
|
|
2252
|
-
function parseStartTag(source, start, end) {
|
|
2253
|
-
const nameResult = readName(source, start + 1, end);
|
|
2254
|
-
let index = nameResult.index;
|
|
2255
|
-
let hasAttribute = false;
|
|
2256
|
-
const attributeNames = /* @__PURE__ */ new Set();
|
|
2257
|
-
while (index < end) {
|
|
2258
|
-
const beforeWhitespace = index;
|
|
2259
|
-
index = skipWhitespace(source, index);
|
|
2260
|
-
if (index === end) {
|
|
2261
|
-
break;
|
|
2262
|
-
}
|
|
2263
|
-
if (source[index] === "/") {
|
|
2264
|
-
if (index + 1 !== end) {
|
|
2265
|
-
fail("Invalid XML self-closing tag");
|
|
2266
|
-
}
|
|
2267
|
-
return { name: nameResult.name, selfClosing: true };
|
|
2268
|
-
}
|
|
2269
|
-
if (hasAttribute && beforeWhitespace === index) {
|
|
2270
|
-
fail("XML attributes must be separated by whitespace");
|
|
2271
|
-
}
|
|
2272
|
-
const attribute = readName(source, index, end);
|
|
2273
|
-
index = skipWhitespace(source, attribute.index);
|
|
2274
|
-
if (source[index] !== "=") {
|
|
2275
|
-
fail(`XML attribute ${attribute.name} must have a value`);
|
|
2276
|
-
}
|
|
2277
|
-
index = skipWhitespace(source, index + 1);
|
|
2278
|
-
const quote = source[index];
|
|
2279
|
-
if (quote !== '"' && quote !== "'") {
|
|
2280
|
-
fail(`XML attribute ${attribute.name} must use a quoted value`);
|
|
2281
|
-
}
|
|
2282
|
-
index += 1;
|
|
2283
|
-
const valueStart = index;
|
|
2284
|
-
while (index < end && source[index] !== quote) {
|
|
2285
|
-
if (source[index] === "<") {
|
|
2286
|
-
fail(`Invalid "<" in XML attribute ${attribute.name}`);
|
|
2287
|
-
}
|
|
2288
|
-
index += 1;
|
|
2289
|
-
}
|
|
2290
|
-
if (index === end) {
|
|
2291
|
-
fail(`Unclosed XML attribute ${attribute.name}`);
|
|
2292
|
-
}
|
|
2293
|
-
if (attributeNames.has(attribute.name)) {
|
|
2294
|
-
fail(`Duplicate XML attribute: ${attribute.name}`);
|
|
2295
|
-
}
|
|
2296
|
-
attributeNames.add(attribute.name);
|
|
2297
|
-
validateEntityReferences(source.slice(valueStart, index));
|
|
2298
|
-
index += 1;
|
|
2299
|
-
hasAttribute = true;
|
|
2300
|
-
}
|
|
2301
|
-
return { name: nameResult.name, selfClosing: false };
|
|
2302
|
-
}
|
|
2303
|
-
function parseClosingTag(source, start, end) {
|
|
2304
|
-
const nameResult = readName(source, start + 2, end);
|
|
2305
|
-
if (skipWhitespace(source, nameResult.index) !== end) {
|
|
2306
|
-
fail("Invalid XML closing tag");
|
|
2307
|
-
}
|
|
2308
|
-
return nameResult.name;
|
|
2309
|
-
}
|
|
2310
|
-
function parseProcessingInstruction(source, start, end) {
|
|
2311
|
-
readName(source, start + 2, end);
|
|
2312
|
-
}
|
|
2313
|
-
function parseDeclaration(source, start, end) {
|
|
2314
|
-
readName(source, start + 2, end);
|
|
2315
|
-
}
|
|
2316
|
-
function appendNode2(nodes, node) {
|
|
2317
|
-
const previous = nodes[nodes.length - 1];
|
|
2318
|
-
if (node.kind === "text" && previous?.kind === "text") {
|
|
2319
|
-
previous.value += node.value;
|
|
2320
|
-
return;
|
|
2321
|
-
}
|
|
2322
|
-
nodes.push(node);
|
|
2323
|
-
}
|
|
2324
|
-
function currentElement(stack) {
|
|
2325
|
-
return stack[stack.length - 1];
|
|
2326
|
-
}
|
|
2327
|
-
function parseXml(source) {
|
|
2328
|
-
const children = [];
|
|
2329
|
-
const stack = [];
|
|
2330
|
-
let root;
|
|
2331
|
-
let index = 0;
|
|
2332
|
-
while (index < source.length) {
|
|
2333
|
-
if (source[index] !== "<") {
|
|
2334
|
-
const textStart = index;
|
|
2335
|
-
while (index < source.length && source[index] !== "<") {
|
|
2336
|
-
index += 1;
|
|
2337
|
-
}
|
|
2338
|
-
const value = source.slice(textStart, index);
|
|
2339
|
-
if (value.includes("]]>")) {
|
|
2340
|
-
fail("CDATA termination is not valid in ordinary XML text");
|
|
2341
|
-
}
|
|
2342
|
-
validateEntityReferences(value);
|
|
2343
|
-
if (stack.length === 0 && value.trim() !== "") {
|
|
2344
|
-
fail("Unexpected text outside the root XML element");
|
|
2345
|
-
}
|
|
2346
|
-
appendNode2(currentElement(stack)?.children ?? children, { kind: "text", value });
|
|
2347
|
-
continue;
|
|
2348
|
-
}
|
|
2349
|
-
if (source.startsWith("<!--", index)) {
|
|
2350
|
-
const end2 = source.indexOf("-->", index + 4);
|
|
2351
|
-
if (end2 === -1) {
|
|
2352
|
-
fail("Unclosed XML comment");
|
|
2353
|
-
}
|
|
2354
|
-
const content = source.slice(index + 4, end2);
|
|
2355
|
-
if (content.includes("--") || content.endsWith("-")) {
|
|
2356
|
-
fail("Invalid XML comment");
|
|
2357
|
-
}
|
|
2358
|
-
appendNode2(currentElement(stack)?.children ?? children, {
|
|
2359
|
-
kind: "comment",
|
|
2360
|
-
raw: source.slice(index, end2 + 3)
|
|
2361
|
-
});
|
|
2362
|
-
index = end2 + 3;
|
|
2363
|
-
continue;
|
|
2364
|
-
}
|
|
2365
|
-
if (source.startsWith("<![CDATA[", index)) {
|
|
2366
|
-
const end2 = source.indexOf("]]>", index + "<![CDATA[".length);
|
|
2367
|
-
if (end2 === -1) {
|
|
2368
|
-
fail("Unclosed XML CDATA section");
|
|
2369
|
-
}
|
|
2370
|
-
if (stack.length === 0) {
|
|
2371
|
-
fail("CDATA is not allowed outside the root XML element");
|
|
2372
|
-
}
|
|
2373
|
-
appendNode2(currentElement(stack)?.children ?? children, {
|
|
2374
|
-
kind: "cdata",
|
|
2375
|
-
raw: source.slice(index, end2 + 3)
|
|
2376
|
-
});
|
|
2377
|
-
index = end2 + 3;
|
|
2378
|
-
continue;
|
|
2379
|
-
}
|
|
2380
|
-
if (source.startsWith("<?", index)) {
|
|
2381
|
-
const end2 = source.indexOf("?>", index + 2);
|
|
2382
|
-
if (end2 === -1) {
|
|
2383
|
-
fail("Unclosed XML processing instruction");
|
|
2384
|
-
}
|
|
2385
|
-
parseProcessingInstruction(source, index, end2);
|
|
2386
|
-
appendNode2(currentElement(stack)?.children ?? children, {
|
|
2387
|
-
kind: "processing-instruction",
|
|
2388
|
-
raw: source.slice(index, end2 + 2)
|
|
2389
|
-
});
|
|
2390
|
-
index = end2 + 2;
|
|
2391
|
-
continue;
|
|
2392
|
-
}
|
|
2393
|
-
if (source.startsWith("</", index)) {
|
|
2394
|
-
const end2 = findTagEnd(source, index);
|
|
2395
|
-
const name2 = parseClosingTag(source, index, end2);
|
|
2396
|
-
const element = currentElement(stack);
|
|
2397
|
-
if (element === void 0 || element.name !== name2) {
|
|
2398
|
-
fail(`Mismatched closing XML element: </${name2}>`);
|
|
2399
|
-
}
|
|
2400
|
-
element.close = source.slice(index, end2 + 1);
|
|
2401
|
-
stack.pop();
|
|
2402
|
-
index = end2 + 1;
|
|
2403
|
-
continue;
|
|
2404
|
-
}
|
|
2405
|
-
if (source.startsWith("<!", index)) {
|
|
2406
|
-
const end2 = findTagEnd(source, index, true);
|
|
2407
|
-
parseDeclaration(source, index, end2);
|
|
2408
|
-
appendNode2(currentElement(stack)?.children ?? children, {
|
|
2409
|
-
kind: "declaration",
|
|
2410
|
-
raw: source.slice(index, end2 + 1)
|
|
2411
|
-
});
|
|
2412
|
-
index = end2 + 1;
|
|
2413
|
-
continue;
|
|
2414
|
-
}
|
|
2415
|
-
const end = findTagEnd(source, index);
|
|
2416
|
-
const { name, selfClosing } = parseStartTag(source, index, end);
|
|
2417
|
-
if (stack.length === 0) {
|
|
2418
|
-
if (root !== void 0) {
|
|
2419
|
-
fail("Multiple root XML elements are not allowed");
|
|
2420
|
-
}
|
|
2421
|
-
root = {
|
|
2422
|
-
kind: "element",
|
|
2423
|
-
name,
|
|
2424
|
-
open: source.slice(index, end + 1),
|
|
2425
|
-
selfClosing,
|
|
2426
|
-
children: []
|
|
2427
|
-
};
|
|
2428
|
-
children.push(root);
|
|
2429
|
-
} else {
|
|
2430
|
-
const element = {
|
|
2431
|
-
kind: "element",
|
|
2432
|
-
name,
|
|
2433
|
-
open: source.slice(index, end + 1),
|
|
2434
|
-
selfClosing,
|
|
2435
|
-
children: []
|
|
2436
|
-
};
|
|
2437
|
-
currentElement(stack)?.children.push(element);
|
|
2438
|
-
if (!selfClosing) {
|
|
2439
|
-
stack.push(element);
|
|
2440
|
-
}
|
|
2441
|
-
index = end + 1;
|
|
2442
|
-
continue;
|
|
2443
|
-
}
|
|
2444
|
-
if (!selfClosing) {
|
|
2445
|
-
stack.push(root);
|
|
2446
|
-
}
|
|
2447
|
-
index = end + 1;
|
|
2448
|
-
}
|
|
2449
|
-
if (stack.length > 0) {
|
|
2450
|
-
fail(`Unclosed XML element: <${currentElement(stack)?.name}>`);
|
|
2451
|
-
}
|
|
2452
|
-
if (root === void 0) {
|
|
2453
|
-
fail("XML input does not contain a root element");
|
|
2454
|
-
}
|
|
2455
|
-
return { children, root };
|
|
2456
|
-
}
|
|
2457
|
-
function indentation(depth) {
|
|
2458
|
-
return INDENT.repeat(depth);
|
|
2459
|
-
}
|
|
2460
|
-
function renderInline(node) {
|
|
2461
|
-
const content = node.children.map((child) => {
|
|
2462
|
-
if (child.kind === "element") {
|
|
2463
|
-
return renderInline(child);
|
|
2464
|
-
}
|
|
2465
|
-
return child.kind === "text" ? child.value : child.raw;
|
|
2466
|
-
}).join("");
|
|
2467
|
-
return `${node.open}${content}${node.close ?? ""}`;
|
|
2468
|
-
}
|
|
2469
|
-
function hasOnlyTextChildren(node) {
|
|
2470
|
-
return node.children.every((child) => child.kind === "text");
|
|
2471
|
-
}
|
|
2472
|
-
function hasSignificantText(node) {
|
|
2473
|
-
return node.children.some((child) => child.kind === "text" && child.value.trim() !== "");
|
|
2474
|
-
}
|
|
2475
|
-
function hasOnlyWhitespaceText(node) {
|
|
2476
|
-
return node.children.every((child) => child.kind === "text" && child.value.trim() === "");
|
|
2477
|
-
}
|
|
2478
|
-
function toSelfClosingTag(open) {
|
|
2479
|
-
return `${open.slice(0, -1).trimEnd()}/>`;
|
|
2480
|
-
}
|
|
2481
|
-
function formatElement(node, depth, isRoot) {
|
|
2482
|
-
const prefix = indentation(depth);
|
|
2483
|
-
if (node.selfClosing) {
|
|
2484
|
-
return [`${prefix}${node.open}`];
|
|
2485
|
-
}
|
|
2486
|
-
if (node.close === void 0) {
|
|
2487
|
-
fail(`Unclosed XML element: <${node.name}>`);
|
|
2488
|
-
}
|
|
2489
|
-
if (INTRINSICALLY_EMPTY_ELEMENTS.has(node.name) && hasOnlyWhitespaceText(node)) {
|
|
2490
|
-
return [`${prefix}${toSelfClosingTag(node.open)}`];
|
|
2491
|
-
}
|
|
2492
|
-
if (isRoot && hasOnlyTextChildren(node)) {
|
|
2493
|
-
const text = node.children.filter((child) => child.kind === "text").map((child) => child.value).join("");
|
|
2494
|
-
const trimmedText = text.trim();
|
|
2495
|
-
if (trimmedText === "") {
|
|
2496
|
-
return [`${prefix}${node.open}`, `${prefix}${node.close}`];
|
|
2497
|
-
}
|
|
2498
|
-
if (text.includes("\n") || text.includes("\r") || text !== trimmedText) {
|
|
2499
|
-
return [`${prefix}${renderInline(node)}`];
|
|
2500
|
-
}
|
|
2501
|
-
return [`${prefix}${node.open}`, `${indentation(depth + 1)}${trimmedText}`, `${prefix}${node.close}`];
|
|
2502
|
-
}
|
|
2503
|
-
if (hasSignificantText(node)) {
|
|
2504
|
-
return [`${prefix}${renderInline(node)}`];
|
|
2505
|
-
}
|
|
2506
|
-
const lines = [`${prefix}${node.open}`];
|
|
2507
|
-
for (const child of node.children) {
|
|
2508
|
-
if (child.kind === "text") {
|
|
2509
|
-
continue;
|
|
2510
|
-
}
|
|
2511
|
-
if (child.kind === "element") {
|
|
2512
|
-
lines.push(...formatElement(child, depth + 1, false));
|
|
2513
|
-
} else {
|
|
2514
|
-
lines.push(`${indentation(depth + 1)}${child.raw}`);
|
|
2515
|
-
}
|
|
2516
|
-
}
|
|
2517
|
-
lines.push(`${prefix}${node.close}`);
|
|
2518
|
-
return lines;
|
|
2519
|
-
}
|
|
2520
|
-
function stripTrailingWhitespace(value) {
|
|
2521
|
-
return value.replace(/[ \t]+$/gm, "");
|
|
2522
|
-
}
|
|
2523
|
-
function getTrailingLineBreaks(value) {
|
|
2524
|
-
let start = value.length;
|
|
2525
|
-
while (start > 0) {
|
|
2526
|
-
if (value[start - 1] === "\n") {
|
|
2527
|
-
start -= 1;
|
|
2528
|
-
if (start > 0 && value[start - 1] === "\r") {
|
|
2529
|
-
start -= 1;
|
|
2530
|
-
}
|
|
2531
|
-
continue;
|
|
2532
|
-
}
|
|
2533
|
-
if (value[start - 1] === "\r") {
|
|
2534
|
-
start -= 1;
|
|
2535
|
-
continue;
|
|
2536
|
-
}
|
|
2537
|
-
break;
|
|
2538
|
-
}
|
|
2539
|
-
return value.slice(start);
|
|
2540
|
-
}
|
|
2541
|
-
function stripTrailingLineBreaks(value) {
|
|
2542
|
-
let end = value.length;
|
|
2543
|
-
while (end > 0) {
|
|
2544
|
-
if (value[end - 1] === "\n") {
|
|
2545
|
-
end -= 1;
|
|
2546
|
-
if (end > 0 && value[end - 1] === "\r") {
|
|
2547
|
-
end -= 1;
|
|
2548
|
-
}
|
|
2549
|
-
continue;
|
|
2550
|
-
}
|
|
2551
|
-
if (value[end - 1] === "\r") {
|
|
2552
|
-
end -= 1;
|
|
2553
|
-
continue;
|
|
2554
|
-
}
|
|
2555
|
-
break;
|
|
2556
|
-
}
|
|
2557
|
-
return value.slice(0, end);
|
|
2558
|
-
}
|
|
2559
|
-
function preserveTrailingLineBreak(formatted, trailingLineBreaks) {
|
|
2560
|
-
if (trailingLineBreaks === "") {
|
|
2561
|
-
return formatted;
|
|
2562
|
-
}
|
|
2563
|
-
return `${stripTrailingLineBreaks(formatted)}${trailingLineBreaks}`;
|
|
2564
|
-
}
|
|
2565
|
-
function renderDocument(document2) {
|
|
2566
|
-
const lines = [];
|
|
2567
|
-
for (const child of document2.children) {
|
|
2568
|
-
if (child.kind === "text") {
|
|
2569
|
-
continue;
|
|
2570
|
-
}
|
|
2571
|
-
if (child.kind === "element") {
|
|
2572
|
-
lines.push(...formatElement(child, 0, child === document2.root));
|
|
2573
|
-
} else {
|
|
2574
|
-
lines.push(child.raw);
|
|
2575
|
-
}
|
|
2576
|
-
}
|
|
2577
|
-
return stripTrailingWhitespace(lines.join("\n")).trim();
|
|
2578
|
-
}
|
|
2579
|
-
function unwrapFormattedFragment(formatted) {
|
|
2580
|
-
const opening = `<${FRAGMENT_ROOT}>`;
|
|
2581
|
-
const closing = `</${FRAGMENT_ROOT}>`;
|
|
2582
|
-
if (!formatted.startsWith(opening) || !formatted.endsWith(closing)) {
|
|
2583
|
-
return void 0;
|
|
2584
|
-
}
|
|
2585
|
-
if (formatted === `${opening}${closing}`) {
|
|
2586
|
-
return "";
|
|
2587
|
-
}
|
|
2588
|
-
const multilineOpening = `${opening}
|
|
2589
|
-
`;
|
|
2590
|
-
const multilineClosing = `
|
|
2591
|
-
${closing}`;
|
|
2592
|
-
if (formatted.startsWith(multilineOpening) && formatted.endsWith(multilineClosing)) {
|
|
2593
|
-
const content = formatted.slice(multilineOpening.length, -multilineClosing.length);
|
|
2594
|
-
return content.split("\n").map((line) => line.startsWith(INDENT) ? line.slice(INDENT.length) : line).join("\n");
|
|
2595
|
-
}
|
|
2596
|
-
return formatted.slice(opening.length, -closing.length);
|
|
2597
|
-
}
|
|
2598
|
-
function formatXmlFragment(xml) {
|
|
2599
|
-
const trailingLineBreaks = getTrailingLineBreaks(xml);
|
|
2600
|
-
const source = xml.trim();
|
|
2601
|
-
if (source === "") {
|
|
2602
|
-
return "";
|
|
2603
|
-
}
|
|
2604
|
-
const wrapped = `<${FRAGMENT_ROOT}>${source}</${FRAGMENT_ROOT}>`;
|
|
2605
|
-
let formatted;
|
|
2606
|
-
try {
|
|
2607
|
-
formatted = renderDocument(parseXml(wrapped));
|
|
2608
|
-
} catch {
|
|
2609
|
-
return xml;
|
|
2610
|
-
}
|
|
2611
|
-
return preserveTrailingLineBreak(unwrapFormattedFragment(formatted) ?? xml, trailingLineBreaks);
|
|
2612
|
-
}
|
|
2613
|
-
|
|
2614
|
-
// packages/ssml-editor-react/src/ssmlInsertion.ts
|
|
2615
|
-
function isLineStart(value, offset) {
|
|
2616
|
-
return offset === 0 || value[offset - 1] === "\n" || value[offset - 1] === "\r";
|
|
2617
|
-
}
|
|
2618
|
-
function isLineEnd(value, offset) {
|
|
2619
|
-
return offset === value.length || value[offset] === "\n" || value[offset] === "\r";
|
|
2620
|
-
}
|
|
2621
|
-
function getLineBreakAt(value, offset) {
|
|
2622
|
-
if (value.startsWith("\r\n", offset)) {
|
|
2623
|
-
return "\r\n";
|
|
337
|
+
lineHeight: 1.5
|
|
2624
338
|
}
|
|
2625
|
-
|
|
2626
|
-
|
|
339
|
+
};
|
|
340
|
+
|
|
341
|
+
// packages/ssml-editor-react/src/components/popovers/InsertionPopover.tsx
|
|
342
|
+
function getInsertionTitle(insertion, language) {
|
|
343
|
+
if (insertion.titles) {
|
|
344
|
+
return insertion.titles[language];
|
|
2627
345
|
}
|
|
2628
|
-
|
|
2629
|
-
}
|
|
2630
|
-
function startsWithLineBreak(value) {
|
|
2631
|
-
return value.startsWith("\n") || value.startsWith("\r");
|
|
346
|
+
const tag = insertion.tagName ? ` <${insertion.tagName}${insertion.selfClosing ? "/>" : ">"}` : "";
|
|
347
|
+
return `${insertion.labels[language]}${tag} \u2014 ${insertion.descriptions[language]}`;
|
|
2632
348
|
}
|
|
2633
|
-
function
|
|
2634
|
-
|
|
349
|
+
function InsertionPopover({
|
|
350
|
+
insertion,
|
|
351
|
+
language,
|
|
352
|
+
isDarkTheme,
|
|
353
|
+
showToolbarIcons,
|
|
354
|
+
showToolbarText,
|
|
355
|
+
toolbarButtonStyle,
|
|
356
|
+
emptyOptionsMessage,
|
|
357
|
+
isReadOnly,
|
|
358
|
+
isOpen,
|
|
359
|
+
menuPosition,
|
|
360
|
+
menuRef,
|
|
361
|
+
onToggle,
|
|
362
|
+
onClose,
|
|
363
|
+
onApply,
|
|
364
|
+
optionGroups
|
|
365
|
+
}) {
|
|
366
|
+
const hasOptions = optionGroups ? optionGroups.some((group) => group.options.length > 0) : insertion.options.length > 0;
|
|
367
|
+
const renderOption = (option) => /* @__PURE__ */ React.createElement(
|
|
368
|
+
"button",
|
|
369
|
+
{
|
|
370
|
+
key: option.value,
|
|
371
|
+
type: "button",
|
|
372
|
+
role: "menuitem",
|
|
373
|
+
style: editorStyles.toolbarOption,
|
|
374
|
+
title: option.descriptions?.[language] ?? insertion.descriptions[language],
|
|
375
|
+
disabled: isReadOnly,
|
|
376
|
+
onMouseDown: (event) => event.preventDefault(),
|
|
377
|
+
onClick: () => {
|
|
378
|
+
if (!isReadOnly) {
|
|
379
|
+
onApply(insertion, option);
|
|
380
|
+
}
|
|
381
|
+
onClose();
|
|
382
|
+
}
|
|
383
|
+
},
|
|
384
|
+
option.labels[language]
|
|
385
|
+
);
|
|
386
|
+
const menu = isOpen && menuPosition && typeof document !== "undefined" ? /* @__PURE__ */ React.createElement(
|
|
387
|
+
"div",
|
|
388
|
+
{
|
|
389
|
+
ref: menuRef,
|
|
390
|
+
id: `ssml-editor-popover-${insertion.id}`,
|
|
391
|
+
"data-ssml-editor": "",
|
|
392
|
+
"data-theme": isDarkTheme ? "dark" : "light",
|
|
393
|
+
style: { ...editorStyles.toolbarMenu, top: menuPosition.top, left: menuPosition.left },
|
|
394
|
+
role: "menu",
|
|
395
|
+
"aria-label": insertion.labels[language]
|
|
396
|
+
},
|
|
397
|
+
!hasOptions ? /* @__PURE__ */ React.createElement("div", { role: "presentation" }, /* @__PURE__ */ React.createElement("select", { disabled: true, value: "", style: editorStyles.toolbarEmptySelect }, /* @__PURE__ */ React.createElement("option", { value: "", disabled: true }, emptyOptionsMessage))) : optionGroups ? optionGroups.map((group) => /* @__PURE__ */ React.createElement("fieldset", { key: group.label, style: editorStyles.toolbarOptionGroup }, /* @__PURE__ */ React.createElement("legend", { style: editorStyles.toolbarOptionGroupLabel }, group.label), group.options.map(renderOption))) : insertion.options.map(renderOption)
|
|
398
|
+
) : null;
|
|
399
|
+
return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("div", { style: editorStyles.toolbarDropdown }, /* @__PURE__ */ React.createElement(
|
|
400
|
+
"button",
|
|
401
|
+
{
|
|
402
|
+
type: "button",
|
|
403
|
+
style: toolbarButtonStyle,
|
|
404
|
+
title: getInsertionTitle(insertion, language),
|
|
405
|
+
"aria-label": insertion.labels[language],
|
|
406
|
+
"aria-haspopup": "menu",
|
|
407
|
+
"aria-expanded": isOpen,
|
|
408
|
+
"aria-controls": isOpen ? `ssml-editor-popover-${insertion.id}` : void 0,
|
|
409
|
+
onClick: (event) => onToggle(event.currentTarget)
|
|
410
|
+
},
|
|
411
|
+
showToolbarIcons && /* @__PURE__ */ React.createElement("span", { style: editorStyles.toolbarIcon, "aria-hidden": "true" }, insertion.icon),
|
|
412
|
+
showToolbarText && /* @__PURE__ */ React.createElement("span", null, insertion.labels[language]),
|
|
413
|
+
/* @__PURE__ */ React.createElement("span", { style: editorStyles.toolbarChevron, "aria-hidden": "true" }, "\u25BE")
|
|
414
|
+
)), menu && createPortal(menu, document.body));
|
|
2635
415
|
}
|
|
2636
|
-
|
|
2637
|
-
|
|
2638
|
-
|
|
2639
|
-
|
|
2640
|
-
|
|
2641
|
-
|
|
2642
|
-
|
|
2643
|
-
|
|
2644
|
-
|
|
2645
|
-
|
|
2646
|
-
|
|
2647
|
-
|
|
2648
|
-
|
|
2649
|
-
|
|
2650
|
-
|
|
2651
|
-
|
|
2652
|
-
|
|
416
|
+
|
|
417
|
+
// packages/ssml-editor-react/src/components/popovers/InsertionPopovers.tsx
|
|
418
|
+
function InsertionPopovers({
|
|
419
|
+
insertions,
|
|
420
|
+
openPopoverId,
|
|
421
|
+
onToggle,
|
|
422
|
+
emptyOptionsMessages,
|
|
423
|
+
optionGroups,
|
|
424
|
+
...props
|
|
425
|
+
}) {
|
|
426
|
+
return /* @__PURE__ */ React.createElement(React.Fragment, null, insertions.map((insertion) => /* @__PURE__ */ React.createElement(
|
|
427
|
+
InsertionPopover,
|
|
428
|
+
{
|
|
429
|
+
key: insertion.id,
|
|
430
|
+
...props,
|
|
431
|
+
insertion,
|
|
432
|
+
emptyOptionsMessage: emptyOptionsMessages?.[insertion.id] ?? props.emptyOptionsMessage,
|
|
433
|
+
optionGroups: optionGroups?.[insertion.id],
|
|
434
|
+
isOpen: openPopoverId === insertion.id,
|
|
435
|
+
onToggle: (trigger) => onToggle(insertion.id, trigger)
|
|
436
|
+
}
|
|
437
|
+
)));
|
|
2653
438
|
}
|
|
2654
439
|
|
|
2655
|
-
// packages/ssml-editor-react/src/
|
|
2656
|
-
|
|
2657
|
-
|
|
2658
|
-
|
|
2659
|
-
|
|
2660
|
-
|
|
2661
|
-
|
|
2662
|
-
|
|
2663
|
-
|
|
2664
|
-
|
|
440
|
+
// packages/ssml-editor-react/src/components/popovers/ProsodyPopovers.tsx
|
|
441
|
+
var CATEGORY_LABEL_KEYS = {
|
|
442
|
+
emotions: "categoryEmotions",
|
|
443
|
+
scenarios: "categoryScenarios",
|
|
444
|
+
media: "categoryMedia",
|
|
445
|
+
other: "categoryOther"
|
|
446
|
+
};
|
|
447
|
+
var CATEGORY_ORDER = ["emotions", "scenarios", "media", "other"];
|
|
448
|
+
function isExpressAsInsertion(insertion) {
|
|
449
|
+
return insertion.id === "emotion" && insertion.tagName?.toLowerCase() === "mstts:express-as";
|
|
450
|
+
}
|
|
451
|
+
function createOptionGroups(options, language) {
|
|
452
|
+
const t = (key) => EDITOR_COPY[language][key];
|
|
453
|
+
return CATEGORY_ORDER.map((category) => ({
|
|
454
|
+
label: t(CATEGORY_LABEL_KEYS[category]),
|
|
455
|
+
options: options.filter((option) => getExpressAsStyleCategory(option.value) === category)
|
|
456
|
+
})).filter((group) => group.options.length > 0);
|
|
457
|
+
}
|
|
458
|
+
function ProsodyPopovers({ insertions, voiceName, language, ...props }) {
|
|
459
|
+
const emptyOptionsMessages = {};
|
|
460
|
+
const filteredInsertions = insertions.map((insertion) => {
|
|
461
|
+
if (!isExpressAsInsertion(insertion)) {
|
|
462
|
+
return insertion;
|
|
2665
463
|
}
|
|
2666
|
-
|
|
2667
|
-
|
|
2668
|
-
|
|
464
|
+
const availableStyles = new Set(
|
|
465
|
+
resolveExpressAsStyles(
|
|
466
|
+
voiceName,
|
|
467
|
+
insertion.options.map((option) => option.value)
|
|
468
|
+
)
|
|
469
|
+
);
|
|
470
|
+
if (availableStyles.size === 0) {
|
|
471
|
+
emptyOptionsMessages[insertion.id] = EDITOR_COPY[language].styleNotSupported;
|
|
2669
472
|
}
|
|
2670
|
-
|
|
2671
|
-
|
|
473
|
+
const availableOptions = insertion.options.filter((option) => availableStyles.has(option.value));
|
|
474
|
+
return {
|
|
475
|
+
...insertion,
|
|
476
|
+
options: availableOptions
|
|
477
|
+
};
|
|
478
|
+
});
|
|
479
|
+
const optionGroups = Object.fromEntries(
|
|
480
|
+
filteredInsertions.filter(isExpressAsInsertion).map((insertion) => [insertion.id, createOptionGroups(insertion.options, language)])
|
|
481
|
+
);
|
|
482
|
+
return /* @__PURE__ */ React.createElement(
|
|
483
|
+
InsertionPopovers,
|
|
484
|
+
{
|
|
485
|
+
...props,
|
|
486
|
+
emptyOptionsMessages,
|
|
487
|
+
language,
|
|
488
|
+
insertions: filteredInsertions,
|
|
489
|
+
optionGroups
|
|
2672
490
|
}
|
|
2673
|
-
|
|
2674
|
-
return -1;
|
|
2675
|
-
}
|
|
2676
|
-
function getVoiceName(tag) {
|
|
2677
|
-
return tag.match(/\bname\s*=\s*(["'])([\s\S]*?)\1/i)?.[2];
|
|
491
|
+
);
|
|
2678
492
|
}
|
|
2679
|
-
|
|
2680
|
-
|
|
2681
|
-
|
|
2682
|
-
|
|
2683
|
-
return;
|
|
2684
|
-
}
|
|
2685
|
-
}
|
|
493
|
+
|
|
494
|
+
// packages/ssml-editor-react/src/components/popovers/TextPopovers.tsx
|
|
495
|
+
function TextPopovers(props) {
|
|
496
|
+
return /* @__PURE__ */ React.createElement(InsertionPopovers, { ...props });
|
|
2686
497
|
}
|
|
2687
|
-
|
|
2688
|
-
|
|
2689
|
-
|
|
2690
|
-
|
|
2691
|
-
while (index < limit) {
|
|
2692
|
-
const tagStart = source.indexOf("<", index);
|
|
2693
|
-
if (tagStart === -1 || tagStart >= limit) {
|
|
2694
|
-
break;
|
|
2695
|
-
}
|
|
2696
|
-
if (source.startsWith("<!--", tagStart)) {
|
|
2697
|
-
const end = source.indexOf("-->", tagStart + 4);
|
|
2698
|
-
index = end === -1 || end + 3 > limit ? limit : end + 3;
|
|
2699
|
-
continue;
|
|
2700
|
-
}
|
|
2701
|
-
if (source.startsWith("<![CDATA[", tagStart)) {
|
|
2702
|
-
const end = source.indexOf("]]>", tagStart + 9);
|
|
2703
|
-
index = end === -1 || end + 3 > limit ? limit : end + 3;
|
|
2704
|
-
continue;
|
|
2705
|
-
}
|
|
2706
|
-
if (source.startsWith("<?", tagStart)) {
|
|
2707
|
-
const end = source.indexOf("?>", tagStart + 2);
|
|
2708
|
-
index = end === -1 || end + 2 > limit ? limit : end + 2;
|
|
2709
|
-
continue;
|
|
2710
|
-
}
|
|
2711
|
-
const tagEnd = findTagEnd2(source, tagStart, limit);
|
|
2712
|
-
if (tagEnd === -1) {
|
|
2713
|
-
break;
|
|
2714
|
-
}
|
|
2715
|
-
const tag = source.slice(tagStart, tagEnd + 1);
|
|
2716
|
-
if (tag.startsWith("<!")) {
|
|
2717
|
-
index = tagEnd + 1;
|
|
2718
|
-
continue;
|
|
2719
|
-
}
|
|
2720
|
-
const closingMatch = tag.match(/^<\s*\/\s*([A-Za-z_][A-Za-z0-9_.:-]*)/);
|
|
2721
|
-
if (closingMatch?.[1]) {
|
|
2722
|
-
closeElement(stack, closingMatch[1].toLowerCase());
|
|
2723
|
-
index = tagEnd + 1;
|
|
2724
|
-
continue;
|
|
2725
|
-
}
|
|
2726
|
-
const openingMatch = tag.match(/^<\s*([A-Za-z_][A-Za-z0-9_.:-]*)/);
|
|
2727
|
-
if (openingMatch?.[1] && !/\/\s*>$/.test(tag)) {
|
|
2728
|
-
const name = openingMatch[1].toLowerCase();
|
|
2729
|
-
stack.push({
|
|
2730
|
-
name,
|
|
2731
|
-
...name === "voice" ? { voiceName: getVoiceName(tag) } : {}
|
|
2732
|
-
});
|
|
2733
|
-
}
|
|
2734
|
-
index = tagEnd + 1;
|
|
2735
|
-
}
|
|
2736
|
-
for (let stackIndex = stack.length - 1; stackIndex >= 0; stackIndex -= 1) {
|
|
2737
|
-
const element = stack[stackIndex];
|
|
2738
|
-
if (element?.name === "voice") {
|
|
2739
|
-
return element.voiceName === void 0 ? {} : { voiceName: element.voiceName };
|
|
2740
|
-
}
|
|
2741
|
-
}
|
|
2742
|
-
return void 0;
|
|
498
|
+
|
|
499
|
+
// packages/ssml-editor-react/src/components/popovers/TimingPopovers.tsx
|
|
500
|
+
function TimingPopovers(props) {
|
|
501
|
+
return /* @__PURE__ */ React.createElement(InsertionPopovers, { ...props });
|
|
2743
502
|
}
|
|
2744
503
|
|
|
2745
504
|
// packages/ssml-editor-react/src/hooks/useSsmlEditorState.ts
|
|
505
|
+
import { useCallback, useEffect, useId, useRef, useState } from "react";
|
|
2746
506
|
var TIMING_INSERTION_TAGS = /* @__PURE__ */ new Set(["break", "mstts:silence"]);
|
|
2747
507
|
var PROSODY_INSERTION_TAGS = /* @__PURE__ */ new Set(["prosody", "mstts:express-as", "voice", "emphasis"]);
|
|
2748
508
|
var TEXT_INSERTION_TAGS = /* @__PURE__ */ new Set(["sub", "say-as", "phoneme", "w", "lang"]);
|
|
@@ -2762,93 +522,11 @@ function isVoice(element) {
|
|
|
2762
522
|
function isProsody(element) {
|
|
2763
523
|
return element.type === "prosody";
|
|
2764
524
|
}
|
|
2765
|
-
function
|
|
2766
|
-
return element.type === "custom" || element.type === "element" ? element.name : element.type;
|
|
2767
|
-
}
|
|
2768
|
-
function findEditableTagEnd(source, start) {
|
|
2769
|
-
let quote;
|
|
2770
|
-
for (let index = start + 1; index < source.length; index += 1) {
|
|
2771
|
-
const character = source[index];
|
|
2772
|
-
if (quote !== void 0) {
|
|
2773
|
-
if (character === quote) {
|
|
2774
|
-
quote = void 0;
|
|
2775
|
-
}
|
|
2776
|
-
continue;
|
|
2777
|
-
}
|
|
2778
|
-
if (character === '"' || character === "'") {
|
|
2779
|
-
quote = character;
|
|
2780
|
-
continue;
|
|
2781
|
-
}
|
|
2782
|
-
if (character === ">") {
|
|
2783
|
-
return index;
|
|
2784
|
-
}
|
|
2785
|
-
}
|
|
2786
|
-
return source.length;
|
|
2787
|
-
}
|
|
2788
|
-
function collectEditableStartTags(source) {
|
|
2789
|
-
const tags = [];
|
|
2790
|
-
let index = 0;
|
|
2791
|
-
while (index < source.length) {
|
|
2792
|
-
if (source[index] !== "<") {
|
|
2793
|
-
index += 1;
|
|
2794
|
-
continue;
|
|
2795
|
-
}
|
|
2796
|
-
if (source.startsWith("<!--", index)) {
|
|
2797
|
-
const end2 = source.indexOf("-->", index + 4);
|
|
2798
|
-
index = end2 === -1 ? source.length : end2 + 3;
|
|
2799
|
-
continue;
|
|
2800
|
-
}
|
|
2801
|
-
if (source.startsWith("<![CDATA[", index)) {
|
|
2802
|
-
const end2 = source.indexOf("]]>", index + 9);
|
|
2803
|
-
index = end2 === -1 ? source.length : end2 + 3;
|
|
2804
|
-
continue;
|
|
2805
|
-
}
|
|
2806
|
-
if (source.startsWith("<?", index)) {
|
|
2807
|
-
const end2 = source.indexOf("?>", index + 2);
|
|
2808
|
-
index = end2 === -1 ? source.length : end2 + 2;
|
|
2809
|
-
continue;
|
|
2810
|
-
}
|
|
2811
|
-
if (source.startsWith("</", index) || source.startsWith("<!", index)) {
|
|
2812
|
-
const end2 = findEditableTagEnd(source, index);
|
|
2813
|
-
index = end2 === source.length ? source.length : end2 + 1;
|
|
2814
|
-
continue;
|
|
2815
|
-
}
|
|
2816
|
-
const end = findEditableTagEnd(source, index);
|
|
2817
|
-
if (end === source.length) {
|
|
2818
|
-
break;
|
|
2819
|
-
}
|
|
2820
|
-
const raw = source.slice(index, end + 1);
|
|
2821
|
-
const match = raw.match(/^<([A-Za-z_][A-Za-z0-9_.:-]*)/);
|
|
2822
|
-
if (match) {
|
|
2823
|
-
tags.push({ name: match[1], selfClosing: /\/\s*>$/.test(raw) });
|
|
2824
|
-
}
|
|
2825
|
-
index = end + 1;
|
|
2826
|
-
}
|
|
2827
|
-
return tags;
|
|
2828
|
-
}
|
|
2829
|
-
function preserveEmptyPairElements(nodes, startTags, startTagIndex) {
|
|
2830
|
-
return nodes.map((node) => {
|
|
2831
|
-
if (!isSsmlElement(node)) {
|
|
2832
|
-
return node;
|
|
2833
|
-
}
|
|
2834
|
-
const elementName = getSsmlElementName(node);
|
|
2835
|
-
const startTag = startTags[startTagIndex.value];
|
|
2836
|
-
startTagIndex.value += 1;
|
|
2837
|
-
if (node.children === void 0 || node.children.length === 0) {
|
|
2838
|
-
return startTag?.name === elementName && !startTag.selfClosing && !INTRINSICALLY_EMPTY_ELEMENTS.has(elementName) ? { ...node, children: [""] } : node;
|
|
2839
|
-
}
|
|
2840
|
-
const children = preserveEmptyPairElements(node.children, startTags, startTagIndex);
|
|
2841
|
-
if (children.every((child, index) => child === node.children?.[index])) {
|
|
2842
|
-
return node;
|
|
2843
|
-
}
|
|
2844
|
-
return { ...node, children };
|
|
2845
|
-
});
|
|
2846
|
-
}
|
|
2847
|
-
function getDocumentChildren2(document2) {
|
|
525
|
+
function getDocumentChildren(document2) {
|
|
2848
526
|
return document2.children ?? (document2.content === void 0 ? [] : [document2.content]);
|
|
2849
527
|
}
|
|
2850
528
|
function getPartialContext(document2) {
|
|
2851
|
-
const children =
|
|
529
|
+
const children = getDocumentChildren(document2);
|
|
2852
530
|
const voice = findFirstElement(children, isVoice);
|
|
2853
531
|
const prosody = findFirstElement(children, isProsody);
|
|
2854
532
|
const context = {
|
|
@@ -2889,112 +567,6 @@ function findFirstElement(nodes, predicate) {
|
|
|
2889
567
|
}
|
|
2890
568
|
return void 0;
|
|
2891
569
|
}
|
|
2892
|
-
function findFirstElementPath(nodes, predicate, ancestors = []) {
|
|
2893
|
-
for (const node of nodes) {
|
|
2894
|
-
if (!isSsmlElement(node)) {
|
|
2895
|
-
continue;
|
|
2896
|
-
}
|
|
2897
|
-
const path = [...ancestors, node];
|
|
2898
|
-
if (predicate(node)) {
|
|
2899
|
-
return path;
|
|
2900
|
-
}
|
|
2901
|
-
const childPath = findFirstElementPath(node.children ?? [], predicate, path);
|
|
2902
|
-
if (childPath) {
|
|
2903
|
-
return childPath;
|
|
2904
|
-
}
|
|
2905
|
-
}
|
|
2906
|
-
return void 0;
|
|
2907
|
-
}
|
|
2908
|
-
function updateFirstElement(nodes, predicate, update) {
|
|
2909
|
-
let updated = false;
|
|
2910
|
-
const nextNodes = nodes.map((node) => {
|
|
2911
|
-
if (updated || !isSsmlElement(node)) {
|
|
2912
|
-
return node;
|
|
2913
|
-
}
|
|
2914
|
-
if (predicate(node)) {
|
|
2915
|
-
updated = true;
|
|
2916
|
-
return update(node);
|
|
2917
|
-
}
|
|
2918
|
-
if (node.children) {
|
|
2919
|
-
const result = updateFirstElement(node.children, predicate, update);
|
|
2920
|
-
if (result.updated) {
|
|
2921
|
-
updated = true;
|
|
2922
|
-
return { ...node, children: result.nodes };
|
|
2923
|
-
}
|
|
2924
|
-
}
|
|
2925
|
-
return node;
|
|
2926
|
-
});
|
|
2927
|
-
return { nodes: nextNodes, updated };
|
|
2928
|
-
}
|
|
2929
|
-
function withChildren(document2, children) {
|
|
2930
|
-
const nextDocument = { ...document2, children };
|
|
2931
|
-
if (nextDocument.content !== void 0) {
|
|
2932
|
-
delete nextDocument.content;
|
|
2933
|
-
}
|
|
2934
|
-
return nextDocument;
|
|
2935
|
-
}
|
|
2936
|
-
function parseEditableText(value, lang) {
|
|
2937
|
-
try {
|
|
2938
|
-
const wrapper = buildSsml({
|
|
2939
|
-
version: "1.0",
|
|
2940
|
-
lang,
|
|
2941
|
-
children: []
|
|
2942
|
-
});
|
|
2943
|
-
const openingTagEnd = wrapper.indexOf(">") + 1;
|
|
2944
|
-
const children = parseSsml(`${wrapper.slice(0, openingTagEnd)}${value}</speak>`).children ?? [];
|
|
2945
|
-
return children.some(isSsmlElement) ? preserveEmptyPairElements(children, collectEditableStartTags(value), { value: 0 }) : [value];
|
|
2946
|
-
} catch {
|
|
2947
|
-
return [value];
|
|
2948
|
-
}
|
|
2949
|
-
}
|
|
2950
|
-
function serializeEditableText(nodes, lang) {
|
|
2951
|
-
if (nodes.length === 1 && typeof nodes[0] === "string") {
|
|
2952
|
-
return nodes[0];
|
|
2953
|
-
}
|
|
2954
|
-
const xml = buildSsml({
|
|
2955
|
-
version: "1.0",
|
|
2956
|
-
lang,
|
|
2957
|
-
children: nodes
|
|
2958
|
-
});
|
|
2959
|
-
const contentStart = xml.indexOf(">") + 1;
|
|
2960
|
-
return xml.slice(contentStart, -"</speak>".length);
|
|
2961
|
-
}
|
|
2962
|
-
function getEditableRegion(document2) {
|
|
2963
|
-
const children = getDocumentChildren2(document2);
|
|
2964
|
-
const path = findFirstElementPath(children, isProsody) ?? findFirstElementPath(children, isVoice);
|
|
2965
|
-
const element = path ? path[path.length - 1] : void 0;
|
|
2966
|
-
const voice = path ? [...path].reverse().find(isVoice) : void 0;
|
|
2967
|
-
return {
|
|
2968
|
-
children: element?.children ?? children,
|
|
2969
|
-
...voice ? { voiceName: voice.name } : {}
|
|
2970
|
-
};
|
|
2971
|
-
}
|
|
2972
|
-
function getEditableChildren(document2) {
|
|
2973
|
-
return getEditableRegion(document2).children;
|
|
2974
|
-
}
|
|
2975
|
-
function getEditableText(document2) {
|
|
2976
|
-
return serializeEditableText(getEditableChildren(document2), document2.lang);
|
|
2977
|
-
}
|
|
2978
|
-
function updateText(document2, value) {
|
|
2979
|
-
const nextChildren = parseEditableText(value, document2.lang);
|
|
2980
|
-
const editableChildren = nextChildren.length > 0 ? nextChildren : [value];
|
|
2981
|
-
const children = getDocumentChildren2(document2);
|
|
2982
|
-
const prosodyResult = updateFirstElement(children, isProsody, (prosody) => ({
|
|
2983
|
-
...prosody,
|
|
2984
|
-
children: editableChildren
|
|
2985
|
-
}));
|
|
2986
|
-
if (prosodyResult.updated) {
|
|
2987
|
-
return withChildren(document2, prosodyResult.nodes);
|
|
2988
|
-
}
|
|
2989
|
-
const voiceResult = updateFirstElement(children, isVoice, (voice) => ({
|
|
2990
|
-
...voice,
|
|
2991
|
-
children: editableChildren
|
|
2992
|
-
}));
|
|
2993
|
-
if (voiceResult.updated) {
|
|
2994
|
-
return withChildren(document2, voiceResult.nodes);
|
|
2995
|
-
}
|
|
2996
|
-
return withChildren(document2, editableChildren);
|
|
2997
|
-
}
|
|
2998
570
|
function getSelectionInfo(editor) {
|
|
2999
571
|
const model = editor.getModel();
|
|
3000
572
|
const selection = editor.getSelection();
|
|
@@ -3130,9 +702,11 @@ function useSsmlEditorState({
|
|
|
3130
702
|
const [decorationsVisible, setDecorationsVisible] = useState(showDecorations);
|
|
3131
703
|
const [isHelpOpen, setIsHelpOpen] = useState(false);
|
|
3132
704
|
const [syntaxError, setSyntaxError] = useState(null);
|
|
705
|
+
const [activeTags, setActiveTags] = useState(() => /* @__PURE__ */ new Set());
|
|
3133
706
|
const [openPopoverId, setOpenPopoverId] = useState(null);
|
|
3134
707
|
const [popoverVoiceName, setPopoverVoiceName] = useState(void 0);
|
|
3135
708
|
const [popoverPosition, setPopoverPosition] = useState(null);
|
|
709
|
+
const pendingCodeLensAttributeRef = useRef(null);
|
|
3136
710
|
const helpPanelId = useId();
|
|
3137
711
|
const draftDocumentRef = useRef(document2);
|
|
3138
712
|
const onSelectionChangeRef = useRef(onSelectionChange);
|
|
@@ -3158,6 +732,7 @@ function useSsmlEditorState({
|
|
|
3158
732
|
setDecorationsVisible(showDecorations);
|
|
3159
733
|
}, [showDecorations]);
|
|
3160
734
|
const closePopover = useCallback((restoreFocus = false) => {
|
|
735
|
+
pendingCodeLensAttributeRef.current = null;
|
|
3161
736
|
setOpenPopoverId(null);
|
|
3162
737
|
setPopoverVoiceName(void 0);
|
|
3163
738
|
setPopoverPosition(null);
|
|
@@ -3166,6 +741,7 @@ function useSsmlEditorState({
|
|
|
3166
741
|
}
|
|
3167
742
|
}, []);
|
|
3168
743
|
const togglePopover = useCallback((id, trigger) => {
|
|
744
|
+
pendingCodeLensAttributeRef.current = null;
|
|
3169
745
|
setOpenPopoverId((currentId) => {
|
|
3170
746
|
if (currentId === id) {
|
|
3171
747
|
setPopoverVoiceName(void 0);
|
|
@@ -3189,13 +765,41 @@ function useSsmlEditorState({
|
|
|
3189
765
|
}
|
|
3190
766
|
const updatePopoverPosition = () => {
|
|
3191
767
|
const trigger = activePopoverTriggerRef.current;
|
|
3192
|
-
if (
|
|
768
|
+
if (trigger) {
|
|
769
|
+
const triggerBounds = trigger.getBoundingClientRect();
|
|
770
|
+
setPopoverPosition({
|
|
771
|
+
top: triggerBounds.bottom + 4,
|
|
772
|
+
left: triggerBounds.left
|
|
773
|
+
});
|
|
774
|
+
return;
|
|
775
|
+
}
|
|
776
|
+
const pending = pendingCodeLensAttributeRef.current;
|
|
777
|
+
const editor = editorRef.current;
|
|
778
|
+
const model = editor?.getModel();
|
|
779
|
+
if (!pending || !editor || !model) {
|
|
780
|
+
return;
|
|
781
|
+
}
|
|
782
|
+
const position = model.getPositionAt(pending.tagRange.start);
|
|
783
|
+
const visiblePosition = editor.getScrolledVisiblePosition(position);
|
|
784
|
+
const editorElement = editor.getDomNode();
|
|
785
|
+
if (!visiblePosition || !editorElement) {
|
|
3193
786
|
return;
|
|
3194
787
|
}
|
|
3195
|
-
const
|
|
788
|
+
const editorBounds = editorElement.getBoundingClientRect();
|
|
789
|
+
const menu = activePopoverMenuRef.current;
|
|
790
|
+
const margin = 8;
|
|
3196
791
|
setPopoverPosition({
|
|
3197
|
-
top:
|
|
3198
|
-
|
|
792
|
+
top: Math.max(
|
|
793
|
+
margin,
|
|
794
|
+
Math.min(
|
|
795
|
+
editorBounds.top + visiblePosition.top + visiblePosition.height + 4,
|
|
796
|
+
window.innerHeight - (menu?.offsetHeight ?? 0) - margin
|
|
797
|
+
)
|
|
798
|
+
),
|
|
799
|
+
left: Math.max(
|
|
800
|
+
margin,
|
|
801
|
+
Math.min(editorBounds.left + visiblePosition.left, window.innerWidth - (menu?.offsetWidth ?? 0) - margin)
|
|
802
|
+
)
|
|
3199
803
|
});
|
|
3200
804
|
};
|
|
3201
805
|
const handlePointerDown = (event) => {
|
|
@@ -3232,6 +836,14 @@ function useSsmlEditorState({
|
|
|
3232
836
|
});
|
|
3233
837
|
}
|
|
3234
838
|
}, []);
|
|
839
|
+
const updateActiveTags = useCallback((nextTags) => {
|
|
840
|
+
setActiveTags((currentTags) => {
|
|
841
|
+
if (currentTags.size === nextTags.size && [...currentTags].every((tag) => nextTags.has(tag))) {
|
|
842
|
+
return currentTags;
|
|
843
|
+
}
|
|
844
|
+
return new Set(nextTags);
|
|
845
|
+
});
|
|
846
|
+
}, []);
|
|
3235
847
|
const commit = useCallback(
|
|
3236
848
|
(nextDocument) => {
|
|
3237
849
|
draftDocumentRef.current = nextDocument;
|
|
@@ -3243,7 +855,7 @@ function useSsmlEditorState({
|
|
|
3243
855
|
);
|
|
3244
856
|
const handleTextChange = useCallback(
|
|
3245
857
|
(value) => {
|
|
3246
|
-
commit(
|
|
858
|
+
commit(updateEditableText(draftDocumentRef.current, value));
|
|
3247
859
|
if (editorRef.current) {
|
|
3248
860
|
refreshSelectionOverlay(editorRef.current, false);
|
|
3249
861
|
}
|
|
@@ -3252,11 +864,48 @@ function useSsmlEditorState({
|
|
|
3252
864
|
);
|
|
3253
865
|
const handleInsert = useCallback(
|
|
3254
866
|
(insertion, option) => {
|
|
3255
|
-
|
|
3256
|
-
|
|
867
|
+
const editor = editorRef.current;
|
|
868
|
+
const pending = pendingCodeLensAttributeRef.current;
|
|
869
|
+
if (!editor) {
|
|
870
|
+
return;
|
|
871
|
+
}
|
|
872
|
+
if (pending?.insertionId === insertion.id) {
|
|
873
|
+
const model = editor.getModel();
|
|
874
|
+
if (model && model.getVersionId() === pending.modelVersionId) {
|
|
875
|
+
const source = model.getValue();
|
|
876
|
+
const tagText = source.slice(pending.tagRange.start, pending.tagRange.end);
|
|
877
|
+
const updatedTag = updateTagAttribute(
|
|
878
|
+
tagText,
|
|
879
|
+
{ start: 0, end: tagText.length },
|
|
880
|
+
pending.attributeName,
|
|
881
|
+
option.value
|
|
882
|
+
);
|
|
883
|
+
const start = model.getPositionAt(pending.tagRange.start);
|
|
884
|
+
const end = model.getPositionAt(pending.tagRange.end);
|
|
885
|
+
editor.pushUndoStop();
|
|
886
|
+
editor.executeEdits("ssml-code-lens", [
|
|
887
|
+
{
|
|
888
|
+
range: {
|
|
889
|
+
startLineNumber: start.lineNumber,
|
|
890
|
+
startColumn: start.column,
|
|
891
|
+
endLineNumber: end.lineNumber,
|
|
892
|
+
endColumn: end.column
|
|
893
|
+
},
|
|
894
|
+
text: updatedTag
|
|
895
|
+
}
|
|
896
|
+
]);
|
|
897
|
+
editor.pushUndoStop();
|
|
898
|
+
editor.focus();
|
|
899
|
+
}
|
|
900
|
+
pendingCodeLensAttributeRef.current = null;
|
|
901
|
+
if (!model || model.getVersionId() !== pending.modelVersionId) {
|
|
902
|
+
closePopover();
|
|
903
|
+
}
|
|
904
|
+
return;
|
|
3257
905
|
}
|
|
906
|
+
applySsmlInsertion(editor, insertion, option);
|
|
3258
907
|
},
|
|
3259
|
-
[]
|
|
908
|
+
[closePopover]
|
|
3260
909
|
);
|
|
3261
910
|
const handleInsertBreak = useCallback(
|
|
3262
911
|
(insertion, option) => {
|
|
@@ -3287,7 +936,7 @@ function useSsmlEditorState({
|
|
|
3287
936
|
}, [commit]);
|
|
3288
937
|
const handleFormat = useCallback(() => {
|
|
3289
938
|
const value = editorRef.current?.getValue() ?? getEditableText(draftDocumentRef.current);
|
|
3290
|
-
commit(
|
|
939
|
+
commit(updateEditableText(draftDocumentRef.current, formatXmlFragment(value)));
|
|
3291
940
|
}, [commit]);
|
|
3292
941
|
const handleUndo = useCallback(() => {
|
|
3293
942
|
editorRef.current?.trigger("toolbar", "undo", null);
|
|
@@ -3317,16 +966,65 @@ function useSsmlEditorState({
|
|
|
3317
966
|
);
|
|
3318
967
|
const getFullSsml = useCallback(
|
|
3319
968
|
() => buildSsml(
|
|
3320
|
-
editorRef.current ?
|
|
969
|
+
editorRef.current ? updateEditableText(draftDocumentRef.current, editorRef.current.getValue()) : draftDocumentRef.current
|
|
3321
970
|
),
|
|
3322
971
|
[]
|
|
3323
972
|
);
|
|
3324
973
|
const getOuterVoiceName = useCallback(() => getEditableRegion(draftDocumentRef.current).voiceName, []);
|
|
974
|
+
const handleCodeLensAction = useCallback((action) => {
|
|
975
|
+
const editor = editorRef.current;
|
|
976
|
+
const model = editor?.getModel();
|
|
977
|
+
if (!editor || !model) {
|
|
978
|
+
return;
|
|
979
|
+
}
|
|
980
|
+
if (action.type === "attribute") {
|
|
981
|
+
pendingCodeLensAttributeRef.current = {
|
|
982
|
+
insertionId: action.insertionId,
|
|
983
|
+
attributeName: action.attributeName,
|
|
984
|
+
tagRange: action.tagRange,
|
|
985
|
+
modelVersionId: model.getVersionId()
|
|
986
|
+
};
|
|
987
|
+
activePopoverTriggerRef.current = null;
|
|
988
|
+
setPopoverVoiceName(getEffectiveVoiceName(editor, draftDocumentRef.current));
|
|
989
|
+
setOpenPopoverId(action.insertionId);
|
|
990
|
+
setPopoverPosition(null);
|
|
991
|
+
return;
|
|
992
|
+
}
|
|
993
|
+
const source = model.getValue();
|
|
994
|
+
const toEditorRange = (range) => {
|
|
995
|
+
const start = model.getPositionAt(range.start);
|
|
996
|
+
const end = model.getPositionAt(range.end);
|
|
997
|
+
return {
|
|
998
|
+
startLineNumber: start.lineNumber,
|
|
999
|
+
startColumn: start.column,
|
|
1000
|
+
endLineNumber: end.lineNumber,
|
|
1001
|
+
endColumn: end.column
|
|
1002
|
+
};
|
|
1003
|
+
};
|
|
1004
|
+
const edits = action.type === "delete" ? [{ range: toEditorRange(action.tagRange), text: "" }] : (() => {
|
|
1005
|
+
const elementText = source.slice(action.elementRange.start, action.elementRange.end);
|
|
1006
|
+
const closingOffset = elementText.search(/<\/\s*prosody\s*>/i);
|
|
1007
|
+
const closingStart = closingOffset === -1 ? action.elementRange.end : action.elementRange.start + closingOffset;
|
|
1008
|
+
const closingEnd = closingOffset === -1 ? action.elementRange.end : source.indexOf(">", closingStart) === -1 ? action.elementRange.end : source.indexOf(">", closingStart) + 1;
|
|
1009
|
+
return [
|
|
1010
|
+
{ range: toEditorRange(action.tagRange), text: "" },
|
|
1011
|
+
{ range: toEditorRange({ start: closingStart, end: closingEnd }), text: "" }
|
|
1012
|
+
];
|
|
1013
|
+
})();
|
|
1014
|
+
editor.pushUndoStop();
|
|
1015
|
+
editor.executeEdits("ssml-code-lens", edits);
|
|
1016
|
+
editor.pushUndoStop();
|
|
1017
|
+
pendingCodeLensAttributeRef.current = null;
|
|
1018
|
+
setOpenPopoverId(null);
|
|
1019
|
+
setPopoverPosition(null);
|
|
1020
|
+
editor.focus();
|
|
1021
|
+
}, []);
|
|
3325
1022
|
return {
|
|
3326
1023
|
editorRef,
|
|
3327
1024
|
draftDocument,
|
|
3328
1025
|
text: getEditableText(draftDocument),
|
|
3329
1026
|
selectionOverlay,
|
|
1027
|
+
activeTags,
|
|
3330
1028
|
isDarkTheme: resolvedTheme === "dark" || resolvedTheme === "system" && isDark,
|
|
3331
1029
|
decorationsVisible,
|
|
3332
1030
|
setDecorationsVisible,
|
|
@@ -3348,10 +1046,12 @@ function useSsmlEditorState({
|
|
|
3348
1046
|
previewSelection,
|
|
3349
1047
|
canPreviewSelection: onPreviewSelection !== void 0,
|
|
3350
1048
|
refreshSelectionOverlay,
|
|
1049
|
+
updateActiveTags,
|
|
3351
1050
|
getSelectedSsml: getSelectedSsmlValue,
|
|
3352
1051
|
getCurrentLineSsml: getCurrentLineSsmlValue,
|
|
3353
1052
|
getFullSsml,
|
|
3354
1053
|
getOuterVoiceName,
|
|
1054
|
+
handleCodeLensAction,
|
|
3355
1055
|
openPopoverId,
|
|
3356
1056
|
popoverVoiceName,
|
|
3357
1057
|
popoverPosition,
|
|
@@ -3500,97 +1200,6 @@ function updateSsmlDiagnostics(monaco, model) {
|
|
|
3500
1200
|
return syntaxError;
|
|
3501
1201
|
}
|
|
3502
1202
|
|
|
3503
|
-
// packages/ssml-editor-react/src/ssmlCompletion.ts
|
|
3504
|
-
var SSML_ATTRIBUTE_VALUE_PATTERN = /<([\w:-]+)\s+[^>]*?\b([\w:-]+)=["']([^"']*)$/i;
|
|
3505
|
-
var EXPRESS_AS_TAG_NAMES = /* @__PURE__ */ new Set(["mstts:express-as", "express-as", "expressas"]);
|
|
3506
|
-
function findSsmlAttributePresets(tagName, attributeName) {
|
|
3507
|
-
const tagPresets = Object.entries(SSML_ATTRIBUTE_PRESETS).find(
|
|
3508
|
-
([presetTagName]) => presetTagName.toLowerCase() === tagName.toLowerCase()
|
|
3509
|
-
)?.[1];
|
|
3510
|
-
return Object.entries(tagPresets ?? {}).find(
|
|
3511
|
-
([presetAttributeName]) => presetAttributeName.toLowerCase() === attributeName.toLowerCase()
|
|
3512
|
-
)?.[1];
|
|
3513
|
-
}
|
|
3514
|
-
var SSML_COMPLETION_SNIPPETS = [
|
|
3515
|
-
{
|
|
3516
|
-
label: "break",
|
|
3517
|
-
insertText: '<break time="500ms" />'
|
|
3518
|
-
},
|
|
3519
|
-
{
|
|
3520
|
-
label: "prosody",
|
|
3521
|
-
insertText: `<prosody rate="medium" pitch="medium">\${1:text}</prosody>`
|
|
3522
|
-
},
|
|
3523
|
-
{
|
|
3524
|
-
label: "mstts:express-as",
|
|
3525
|
-
insertText: `<mstts:express-as style="cheerful">\${1:text}</mstts:express-as>`
|
|
3526
|
-
},
|
|
3527
|
-
{
|
|
3528
|
-
label: "sub",
|
|
3529
|
-
insertText: `<sub alias="\${1:\u8AAD\u307F}">\${2:\u6F22\u5B57}</sub>`
|
|
3530
|
-
}
|
|
3531
|
-
];
|
|
3532
|
-
function registerSsmlCompletionProvider(monaco, options = {}) {
|
|
3533
|
-
const provider = {
|
|
3534
|
-
provideCompletionItems(model, position) {
|
|
3535
|
-
if (options.model && options.model !== model) {
|
|
3536
|
-
return { suggestions: [] };
|
|
3537
|
-
}
|
|
3538
|
-
const value = model.getValue();
|
|
3539
|
-
const offset = model.getOffsetAt(position);
|
|
3540
|
-
const textUntilPosition = value.slice(0, offset);
|
|
3541
|
-
const isClosingTag = /<\/[a-zA-Z0-9:-]*$/.test(textUntilPosition);
|
|
3542
|
-
if (isClosingTag) {
|
|
3543
|
-
return { suggestions: [] };
|
|
3544
|
-
}
|
|
3545
|
-
const attributeMatch = SSML_ATTRIBUTE_VALUE_PATTERN.exec(textUntilPosition);
|
|
3546
|
-
let attributeValues = attributeMatch ? findSsmlAttributePresets(attributeMatch[1], attributeMatch[2]) : void 0;
|
|
3547
|
-
if (attributeMatch && attributeValues && EXPRESS_AS_TAG_NAMES.has(attributeMatch[1].toLowerCase()) && attributeMatch[2].toLowerCase() === "style") {
|
|
3548
|
-
const voiceContext = findSsmlVoiceContext(value, offset);
|
|
3549
|
-
const voiceName = voiceContext === void 0 ? options.getOuterVoiceName?.() : voiceContext.voiceName;
|
|
3550
|
-
attributeValues = resolveExpressAsStyles(voiceName, attributeValues);
|
|
3551
|
-
}
|
|
3552
|
-
const openTagMatch = textUntilPosition.match(/<(?!\/)[a-zA-Z0-9:-]*$/);
|
|
3553
|
-
const openTagLength = openTagMatch?.[0].length ?? 0;
|
|
3554
|
-
const isAfterBracket = model.getValueInRange({
|
|
3555
|
-
startLineNumber: position.lineNumber,
|
|
3556
|
-
startColumn: position.column - 1,
|
|
3557
|
-
endLineNumber: position.lineNumber,
|
|
3558
|
-
endColumn: position.column
|
|
3559
|
-
}) === "<";
|
|
3560
|
-
const hasClosingBracket = isAfterBracket && model.getValueInRange({
|
|
3561
|
-
startLineNumber: position.lineNumber,
|
|
3562
|
-
startColumn: position.column,
|
|
3563
|
-
endLineNumber: position.lineNumber,
|
|
3564
|
-
endColumn: position.column + 1
|
|
3565
|
-
}) === ">";
|
|
3566
|
-
const range = {
|
|
3567
|
-
startLineNumber: position.lineNumber,
|
|
3568
|
-
startColumn: openTagLength > 0 ? position.column - openTagLength : position.column,
|
|
3569
|
-
endLineNumber: position.lineNumber,
|
|
3570
|
-
endColumn: hasClosingBracket ? position.column + 1 : position.column
|
|
3571
|
-
};
|
|
3572
|
-
return {
|
|
3573
|
-
suggestions: [
|
|
3574
|
-
...attributeMatch ? [] : SSML_COMPLETION_SNIPPETS.map(({ label, insertText }) => ({
|
|
3575
|
-
label,
|
|
3576
|
-
kind: monaco.languages.CompletionItemKind.Snippet,
|
|
3577
|
-
insertText,
|
|
3578
|
-
insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet,
|
|
3579
|
-
range
|
|
3580
|
-
})),
|
|
3581
|
-
...attributeValues?.map((value2) => ({
|
|
3582
|
-
label: value2,
|
|
3583
|
-
kind: monaco.languages.CompletionItemKind.Value,
|
|
3584
|
-
insertText: value2
|
|
3585
|
-
})) ?? []
|
|
3586
|
-
]
|
|
3587
|
-
};
|
|
3588
|
-
},
|
|
3589
|
-
triggerCharacters: ["<", '"', "'"]
|
|
3590
|
-
};
|
|
3591
|
-
return monaco.languages.registerCompletionItemProvider("xml", provider);
|
|
3592
|
-
}
|
|
3593
|
-
|
|
3594
1203
|
// packages/ssml-editor-react/src/ssmlCodeAction.ts
|
|
3595
1204
|
var MISSING_TIME_UNIT_ACTION_TITLE = '\u5358\u4F4D "ms" \u3092\u4ED8\u4E0E\u3057\u3066\u4FEE\u5FA9';
|
|
3596
1205
|
function getStructuredMarkerCode(marker) {
|
|
@@ -3699,358 +1308,11 @@ function registerSsmlCodeActions(monaco) {
|
|
|
3699
1308
|
});
|
|
3700
1309
|
}
|
|
3701
1310
|
|
|
3702
|
-
// packages/ssml-editor-react/src/
|
|
3703
|
-
var
|
|
3704
|
-
|
|
3705
|
-
EMPHASIS_LEVEL_PRESETS: EMPHASIS_LEVEL_PRESETS2,
|
|
3706
|
-
PHONEME_ALPHABET_PRESETS: PHONEME_ALPHABET_PRESETS2,
|
|
3707
|
-
PROSODY_RATE_VALUES: PROSODY_RATE_VALUES2,
|
|
3708
|
-
PROSODY_VOLUME_PRESETS: PROSODY_VOLUME_PRESETS2,
|
|
3709
|
-
SILENCE_TYPE_PRESETS: SILENCE_TYPE_PRESETS2,
|
|
3710
|
-
SSML_PRESET_EXAMPLES: SSML_PRESET_EXAMPLES2,
|
|
3711
|
-
VISEME_TYPE_PRESETS: VISEME_TYPE_PRESETS2
|
|
3712
|
-
} = ssmlPresets_exports;
|
|
3713
|
-
var SSML_TAG_DEFINITIONS = [
|
|
3714
|
-
{
|
|
3715
|
-
name: "voice",
|
|
3716
|
-
description: "Selects the voice and optional voice effect used to synthesize the enclosed text.",
|
|
3717
|
-
parameters: [
|
|
3718
|
-
{
|
|
3719
|
-
name: "name",
|
|
3720
|
-
description: "The voice name, such as `en-US-JennyNeural`.",
|
|
3721
|
-
example: "en-US-JennyNeural"
|
|
3722
|
-
},
|
|
3723
|
-
{
|
|
3724
|
-
name: "effect",
|
|
3725
|
-
description: "An optional voice effect, such as `eq_car`."
|
|
3726
|
-
}
|
|
3727
|
-
]
|
|
3728
|
-
},
|
|
3729
|
-
{
|
|
3730
|
-
name: "prosody",
|
|
3731
|
-
description: "Changes the speaking rate, pitch, volume, or pitch contour of the enclosed text.",
|
|
3732
|
-
parameters: [
|
|
3733
|
-
{
|
|
3734
|
-
name: "rate",
|
|
3735
|
-
description: "Controls speaking speed.",
|
|
3736
|
-
values: PROSODY_RATE_VALUES2,
|
|
3737
|
-
example: SSML_PRESET_EXAMPLES2.prosodyRate
|
|
3738
|
-
},
|
|
3739
|
-
{
|
|
3740
|
-
name: "pitch",
|
|
3741
|
-
description: "Adjusts pitch using a named value, percentage, frequency, or semitone value.",
|
|
3742
|
-
example: SSML_PRESET_EXAMPLES2.prosodyPitch
|
|
3743
|
-
},
|
|
3744
|
-
{
|
|
3745
|
-
name: "volume",
|
|
3746
|
-
description: "Controls loudness using a named value, percentage, or decibel value.",
|
|
3747
|
-
values: PROSODY_VOLUME_PRESETS2,
|
|
3748
|
-
example: SSML_PRESET_EXAMPLES2.prosodyVolume
|
|
3749
|
-
},
|
|
3750
|
-
{
|
|
3751
|
-
name: "contour",
|
|
3752
|
-
description: "Defines a sequence of relative pitch changes at positions in the text.",
|
|
3753
|
-
example: "(0%,+0st) (100%,+2st)"
|
|
3754
|
-
},
|
|
3755
|
-
{
|
|
3756
|
-
name: "range",
|
|
3757
|
-
description: "Adjusts the pitch range of the voice.",
|
|
3758
|
-
example: "+2st"
|
|
3759
|
-
}
|
|
3760
|
-
]
|
|
3761
|
-
},
|
|
3762
|
-
{
|
|
3763
|
-
name: "break",
|
|
3764
|
-
description: "Inserts a pause between words or other spoken content.",
|
|
3765
|
-
parameters: [
|
|
3766
|
-
{
|
|
3767
|
-
name: "time",
|
|
3768
|
-
description: "The pause duration, for example `500ms` or `1s`.",
|
|
3769
|
-
example: SSML_PRESET_EXAMPLES2.breakTime
|
|
3770
|
-
},
|
|
3771
|
-
{
|
|
3772
|
-
name: "strength",
|
|
3773
|
-
description: "The relative pause strength.",
|
|
3774
|
-
values: BREAK_STRENGTH_PRESETS2
|
|
3775
|
-
}
|
|
3776
|
-
]
|
|
3777
|
-
},
|
|
3778
|
-
{
|
|
3779
|
-
name: "mstts:express-as",
|
|
3780
|
-
aliases: ["express-as", "expressAs"],
|
|
3781
|
-
description: "Applies a speaking style, style degree, or role to the enclosed text.",
|
|
3782
|
-
parameters: [
|
|
3783
|
-
{
|
|
3784
|
-
name: "style",
|
|
3785
|
-
description: "The speaking style supported by the selected voice, such as `cheerful`.",
|
|
3786
|
-
example: SSML_PRESET_EXAMPLES2.expressAsStyle
|
|
3787
|
-
},
|
|
3788
|
-
{
|
|
3789
|
-
name: "styledegree",
|
|
3790
|
-
aliases: ["style-degree", "styleDegree"],
|
|
3791
|
-
description: "Controls the intensity of the selected speaking style.",
|
|
3792
|
-
example: "1.5"
|
|
3793
|
-
},
|
|
3794
|
-
{
|
|
3795
|
-
name: "role",
|
|
3796
|
-
description: "Changes the speaking role when supported by the selected voice.",
|
|
3797
|
-
example: "YoungAdultFemale"
|
|
3798
|
-
}
|
|
3799
|
-
]
|
|
3800
|
-
},
|
|
3801
|
-
{
|
|
3802
|
-
name: "say-as",
|
|
3803
|
-
aliases: ["sayAs"],
|
|
3804
|
-
description: "Controls how the enclosed text is interpreted and spoken.",
|
|
3805
|
-
parameters: [
|
|
3806
|
-
{
|
|
3807
|
-
name: "interpret-as",
|
|
3808
|
-
description: "Specifies the interpretation, such as characters, digits, date, or time.",
|
|
3809
|
-
example: "characters"
|
|
3810
|
-
},
|
|
3811
|
-
{
|
|
3812
|
-
name: "format",
|
|
3813
|
-
description: "Provides a format hint for the selected interpretation."
|
|
3814
|
-
},
|
|
3815
|
-
{
|
|
3816
|
-
name: "detail",
|
|
3817
|
-
description: "Provides an additional detail hint for the selected interpretation."
|
|
3818
|
-
}
|
|
3819
|
-
]
|
|
3820
|
-
},
|
|
3821
|
-
{
|
|
3822
|
-
name: "phoneme",
|
|
3823
|
-
description: "Replaces normal pronunciation with the supplied phonetic pronunciation.",
|
|
3824
|
-
parameters: [
|
|
3825
|
-
{
|
|
3826
|
-
name: "alphabet",
|
|
3827
|
-
description: "The phonetic alphabet used by the `ph` value.",
|
|
3828
|
-
values: PHONEME_ALPHABET_PRESETS2,
|
|
3829
|
-
example: SSML_PRESET_EXAMPLES2.phonemeAlphabet
|
|
3830
|
-
},
|
|
3831
|
-
{
|
|
3832
|
-
name: "ph",
|
|
3833
|
-
description: "The phonetic pronunciation for the enclosed text.",
|
|
3834
|
-
example: "h\u0259\u02C8lo\u028A"
|
|
3835
|
-
}
|
|
3836
|
-
]
|
|
3837
|
-
},
|
|
3838
|
-
{
|
|
3839
|
-
name: "emphasis",
|
|
3840
|
-
description: "Adds emphasis to the enclosed text.",
|
|
3841
|
-
parameters: [
|
|
3842
|
-
{
|
|
3843
|
-
name: "level",
|
|
3844
|
-
description: "Controls the amount of emphasis.",
|
|
3845
|
-
values: EMPHASIS_LEVEL_PRESETS2
|
|
3846
|
-
}
|
|
3847
|
-
]
|
|
3848
|
-
},
|
|
3849
|
-
{
|
|
3850
|
-
name: "audio",
|
|
3851
|
-
description: "Plays an audio file as part of the synthesized output.",
|
|
3852
|
-
parameters: [
|
|
3853
|
-
{
|
|
3854
|
-
name: "src",
|
|
3855
|
-
description: "The URI of the audio file.",
|
|
3856
|
-
example: "https://example.com/intro.wav"
|
|
3857
|
-
},
|
|
3858
|
-
{
|
|
3859
|
-
name: "desc",
|
|
3860
|
-
description: "Alternative text to use if the audio cannot be played."
|
|
3861
|
-
},
|
|
3862
|
-
{
|
|
3863
|
-
name: "clipBegin",
|
|
3864
|
-
description: "The starting offset within the audio file.",
|
|
3865
|
-
example: "0s"
|
|
3866
|
-
},
|
|
3867
|
-
{
|
|
3868
|
-
name: "clipEnd",
|
|
3869
|
-
description: "The ending offset within the audio file.",
|
|
3870
|
-
example: "5s"
|
|
3871
|
-
},
|
|
3872
|
-
{
|
|
3873
|
-
name: "speed",
|
|
3874
|
-
description: "The playback speed of the audio file.",
|
|
3875
|
-
example: "1.0"
|
|
3876
|
-
},
|
|
3877
|
-
{
|
|
3878
|
-
name: "repeatCount",
|
|
3879
|
-
description: "The number of times to repeat the audio.",
|
|
3880
|
-
example: "2"
|
|
3881
|
-
},
|
|
3882
|
-
{
|
|
3883
|
-
name: "repeatDuration",
|
|
3884
|
-
description: "The total duration for which the audio may repeat.",
|
|
3885
|
-
example: "10s"
|
|
3886
|
-
},
|
|
3887
|
-
{
|
|
3888
|
-
name: "soundLevel",
|
|
3889
|
-
description: "The audio volume adjustment in decibels.",
|
|
3890
|
-
example: "-3dB"
|
|
3891
|
-
}
|
|
3892
|
-
]
|
|
3893
|
-
},
|
|
3894
|
-
{
|
|
3895
|
-
name: "sub",
|
|
3896
|
-
description: "Substitutes the alias text when speaking the enclosed text.",
|
|
3897
|
-
parameters: [
|
|
3898
|
-
{
|
|
3899
|
-
name: "alias",
|
|
3900
|
-
description: "The text to speak instead of the enclosed text.",
|
|
3901
|
-
example: "World Wide Web"
|
|
3902
|
-
}
|
|
3903
|
-
]
|
|
3904
|
-
},
|
|
3905
|
-
{
|
|
3906
|
-
name: "lang",
|
|
3907
|
-
description: "Changes the language used for the enclosed text.",
|
|
3908
|
-
parameters: [
|
|
3909
|
-
{
|
|
3910
|
-
name: "xml:lang",
|
|
3911
|
-
aliases: ["lang"],
|
|
3912
|
-
description: "The BCP-47 language tag.",
|
|
3913
|
-
example: "ja-JP"
|
|
3914
|
-
}
|
|
3915
|
-
]
|
|
3916
|
-
},
|
|
3917
|
-
{
|
|
3918
|
-
name: "mark",
|
|
3919
|
-
description: "Inserts a custom marker into the synthesized audio stream.",
|
|
3920
|
-
parameters: [
|
|
3921
|
-
{
|
|
3922
|
-
name: "name",
|
|
3923
|
-
description: "The application-defined marker name.",
|
|
3924
|
-
example: "chapter-1"
|
|
3925
|
-
}
|
|
3926
|
-
]
|
|
3927
|
-
},
|
|
3928
|
-
{
|
|
3929
|
-
name: "bookmark",
|
|
3930
|
-
description: "Inserts a bookmark marker into the synthesized audio stream.",
|
|
3931
|
-
parameters: [
|
|
3932
|
-
{
|
|
3933
|
-
name: "mark",
|
|
3934
|
-
description: "The application-defined bookmark name.",
|
|
3935
|
-
example: "chapter-1"
|
|
3936
|
-
}
|
|
3937
|
-
]
|
|
3938
|
-
},
|
|
3939
|
-
{
|
|
3940
|
-
name: "lexicon",
|
|
3941
|
-
description: "Associates a pronunciation lexicon with the synthesized document.",
|
|
3942
|
-
parameters: [
|
|
3943
|
-
{
|
|
3944
|
-
name: "uri",
|
|
3945
|
-
description: "The URI of the pronunciation lexicon.",
|
|
3946
|
-
example: "https://example.com/lexicon.pls"
|
|
3947
|
-
}
|
|
3948
|
-
]
|
|
3949
|
-
},
|
|
3950
|
-
{
|
|
3951
|
-
name: "p",
|
|
3952
|
-
description: "Groups text into a paragraph.",
|
|
3953
|
-
parameters: []
|
|
3954
|
-
},
|
|
3955
|
-
{
|
|
3956
|
-
name: "s",
|
|
3957
|
-
description: "Groups text into a sentence.",
|
|
3958
|
-
parameters: []
|
|
3959
|
-
},
|
|
3960
|
-
{
|
|
3961
|
-
name: "w",
|
|
3962
|
-
description: "Groups text into a word.",
|
|
3963
|
-
parameters: []
|
|
3964
|
-
},
|
|
3965
|
-
{
|
|
3966
|
-
name: "mstts:silence",
|
|
3967
|
-
aliases: ["silence"],
|
|
3968
|
-
description: "Adds a specified silence before or after text or at a punctuation boundary.",
|
|
3969
|
-
parameters: [
|
|
3970
|
-
{
|
|
3971
|
-
name: "type",
|
|
3972
|
-
description: "The silence position or punctuation boundary.",
|
|
3973
|
-
values: SILENCE_TYPE_PRESETS2
|
|
3974
|
-
},
|
|
3975
|
-
{
|
|
3976
|
-
name: "value",
|
|
3977
|
-
description: "The silence duration, for example `300ms`.",
|
|
3978
|
-
example: SSML_PRESET_EXAMPLES2.silenceValue
|
|
3979
|
-
}
|
|
3980
|
-
]
|
|
3981
|
-
},
|
|
3982
|
-
{
|
|
3983
|
-
name: "mstts:viseme",
|
|
3984
|
-
aliases: ["viseme"],
|
|
3985
|
-
description: "Requests viseme events for the synthesized audio.",
|
|
3986
|
-
parameters: [
|
|
3987
|
-
{
|
|
3988
|
-
name: "type",
|
|
3989
|
-
description: "The viseme event format.",
|
|
3990
|
-
values: VISEME_TYPE_PRESETS2
|
|
3991
|
-
}
|
|
3992
|
-
]
|
|
3993
|
-
}
|
|
3994
|
-
];
|
|
3995
|
-
var definitionsByName = /* @__PURE__ */ new Map();
|
|
3996
|
-
for (const definition of SSML_TAG_DEFINITIONS) {
|
|
3997
|
-
definitionsByName.set(definition.name, definition);
|
|
3998
|
-
for (const alias of definition.aliases ?? []) {
|
|
3999
|
-
definitionsByName.set(alias, definition);
|
|
4000
|
-
}
|
|
4001
|
-
}
|
|
4002
|
-
function isXmlNameStart3(value) {
|
|
4003
|
-
return value !== void 0 && /[A-Za-z_]/.test(value);
|
|
4004
|
-
}
|
|
4005
|
-
function isXmlNameCharacter3(value) {
|
|
4006
|
-
return value !== void 0 && /[A-Za-z0-9_.:-]/.test(value);
|
|
4007
|
-
}
|
|
4008
|
-
function isXmlWhitespace3(value) {
|
|
4009
|
-
return value === " " || value === " " || value === "\r" || value === "\n";
|
|
4010
|
-
}
|
|
4011
|
-
function positionToOffset(source, lineNumber, column) {
|
|
4012
|
-
if (!Number.isInteger(lineNumber) || !Number.isInteger(column) || lineNumber < 1 || column < 1) {
|
|
4013
|
-
return void 0;
|
|
4014
|
-
}
|
|
4015
|
-
let lineStart = 0;
|
|
4016
|
-
for (let line = 1; line < lineNumber; line += 1) {
|
|
4017
|
-
const newline = source.indexOf("\n", lineStart);
|
|
4018
|
-
if (newline === -1) {
|
|
4019
|
-
return void 0;
|
|
4020
|
-
}
|
|
4021
|
-
lineStart = newline + 1;
|
|
4022
|
-
}
|
|
4023
|
-
const lineEnd = source.indexOf("\n", lineStart);
|
|
4024
|
-
const lineLength = lineEnd === -1 ? source.length - lineStart : lineEnd - lineStart;
|
|
4025
|
-
if (column > lineLength + 1) {
|
|
4026
|
-
return void 0;
|
|
4027
|
-
}
|
|
4028
|
-
return lineStart + column - 1;
|
|
4029
|
-
}
|
|
4030
|
-
function offsetToPosition(source, offset) {
|
|
4031
|
-
const lastNewline = source.lastIndexOf("\n", offset - 1);
|
|
4032
|
-
const lineNumber = source.slice(0, offset).split("\n").length;
|
|
4033
|
-
return {
|
|
4034
|
-
lineNumber,
|
|
4035
|
-
column: offset - lastNewline
|
|
4036
|
-
};
|
|
4037
|
-
}
|
|
4038
|
-
function toRange(source, token) {
|
|
4039
|
-
const start = offsetToPosition(source, token.start);
|
|
4040
|
-
const end = offsetToPosition(source, token.end);
|
|
4041
|
-
return {
|
|
4042
|
-
startLineNumber: start.lineNumber,
|
|
4043
|
-
startColumn: start.column,
|
|
4044
|
-
endLineNumber: end.lineNumber,
|
|
4045
|
-
endColumn: end.column
|
|
4046
|
-
};
|
|
4047
|
-
}
|
|
4048
|
-
function containsOffset(token, offset) {
|
|
4049
|
-
return offset >= token.start && offset < token.end;
|
|
4050
|
-
}
|
|
4051
|
-
function findTagEnd3(source, start) {
|
|
1311
|
+
// packages/ssml-editor-react/src/ssmlCodeLens.ts
|
|
1312
|
+
var CODE_LENS_COMMAND = "ssml-editor.codeLens";
|
|
1313
|
+
function findTagEnd(source, start) {
|
|
4052
1314
|
let quote;
|
|
4053
|
-
for (let index = start; index < source.length; index += 1) {
|
|
1315
|
+
for (let index = start + 1; index < source.length; index += 1) {
|
|
4054
1316
|
const character = source[index];
|
|
4055
1317
|
if (quote !== void 0) {
|
|
4056
1318
|
if (character === quote) {
|
|
@@ -4062,236 +1324,162 @@ function findTagEnd3(source, start) {
|
|
|
4062
1324
|
return index;
|
|
4063
1325
|
}
|
|
4064
1326
|
}
|
|
4065
|
-
return
|
|
1327
|
+
return -1;
|
|
4066
1328
|
}
|
|
4067
|
-
function
|
|
4068
|
-
|
|
4069
|
-
|
|
4070
|
-
|
|
4071
|
-
|
|
4072
|
-
|
|
4073
|
-
}
|
|
4074
|
-
while (index < contentEnd && isXmlWhitespace3(source[index])) {
|
|
4075
|
-
index += 1;
|
|
4076
|
-
}
|
|
4077
|
-
if (!isXmlNameStart3(source[index])) {
|
|
4078
|
-
return void 0;
|
|
4079
|
-
}
|
|
4080
|
-
const nameStart = index;
|
|
4081
|
-
index += 1;
|
|
4082
|
-
while (index < contentEnd && isXmlNameCharacter3(source[index])) {
|
|
4083
|
-
index += 1;
|
|
4084
|
-
}
|
|
4085
|
-
const nameEnd = index;
|
|
4086
|
-
const attributes = [];
|
|
4087
|
-
if (!closing) {
|
|
4088
|
-
while (index < contentEnd) {
|
|
4089
|
-
while (index < contentEnd && isXmlWhitespace3(source[index])) {
|
|
4090
|
-
index += 1;
|
|
4091
|
-
}
|
|
4092
|
-
if (index >= contentEnd || source[index] === "/") {
|
|
4093
|
-
break;
|
|
4094
|
-
}
|
|
4095
|
-
if (!isXmlNameStart3(source[index])) {
|
|
4096
|
-
index += 1;
|
|
4097
|
-
continue;
|
|
4098
|
-
}
|
|
4099
|
-
const attributeStart = index;
|
|
4100
|
-
index += 1;
|
|
4101
|
-
while (index < contentEnd && isXmlNameCharacter3(source[index])) {
|
|
4102
|
-
index += 1;
|
|
4103
|
-
}
|
|
4104
|
-
const attributeEnd = index;
|
|
4105
|
-
while (index < contentEnd && isXmlWhitespace3(source[index])) {
|
|
4106
|
-
index += 1;
|
|
4107
|
-
}
|
|
4108
|
-
let value;
|
|
4109
|
-
if (source[index] === "=") {
|
|
4110
|
-
index += 1;
|
|
4111
|
-
while (index < contentEnd && isXmlWhitespace3(source[index])) {
|
|
4112
|
-
index += 1;
|
|
4113
|
-
}
|
|
4114
|
-
const quote = source[index];
|
|
4115
|
-
if (quote === '"' || quote === "'") {
|
|
4116
|
-
index += 1;
|
|
4117
|
-
const valueStart = index;
|
|
4118
|
-
while (index < contentEnd && source[index] !== quote) {
|
|
4119
|
-
index += 1;
|
|
4120
|
-
}
|
|
4121
|
-
value = { start: valueStart, end: index };
|
|
4122
|
-
if (index < contentEnd) {
|
|
4123
|
-
index += 1;
|
|
4124
|
-
}
|
|
4125
|
-
} else {
|
|
4126
|
-
const valueStart = index;
|
|
4127
|
-
while (index < contentEnd && !isXmlWhitespace3(source[index]) && source[index] !== "/") {
|
|
4128
|
-
index += 1;
|
|
4129
|
-
}
|
|
4130
|
-
value = { start: valueStart, end: index };
|
|
4131
|
-
}
|
|
4132
|
-
}
|
|
4133
|
-
attributes.push({
|
|
4134
|
-
name: { start: attributeStart, end: attributeEnd },
|
|
4135
|
-
value
|
|
4136
|
-
});
|
|
4137
|
-
}
|
|
4138
|
-
}
|
|
4139
|
-
return {
|
|
4140
|
-
name: source.slice(nameStart, nameEnd),
|
|
4141
|
-
nameRange: { start: nameStart, end: nameEnd },
|
|
4142
|
-
start,
|
|
4143
|
-
end: tokenEnd,
|
|
4144
|
-
closing,
|
|
4145
|
-
attributes
|
|
4146
|
-
};
|
|
1329
|
+
function getAttributeValue(tag, attributeName) {
|
|
1330
|
+
const escapedName = attributeName.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
1331
|
+
return tag.match(new RegExp(`\\b${escapedName}\\s*=\\s*(["'])([\\s\\S]*?)\\1`, "i"))?.[2];
|
|
1332
|
+
}
|
|
1333
|
+
function getTagRange(start, end) {
|
|
1334
|
+
return { start, end };
|
|
4147
1335
|
}
|
|
4148
|
-
function
|
|
4149
|
-
|
|
4150
|
-
|
|
4151
|
-
|
|
4152
|
-
|
|
4153
|
-
|
|
1336
|
+
function getElementEnd(source, tagName, tagEnd) {
|
|
1337
|
+
const openingTag = source.slice(0, tagEnd + 1);
|
|
1338
|
+
if (/\/\s*>$/.test(openingTag)) {
|
|
1339
|
+
return tagEnd + 1;
|
|
1340
|
+
}
|
|
1341
|
+
let depth = 1;
|
|
1342
|
+
let index = tagEnd + 1;
|
|
1343
|
+
while (index < source.length) {
|
|
1344
|
+
const nextStart = source.indexOf("<", index);
|
|
1345
|
+
if (nextStart === -1) {
|
|
1346
|
+
break;
|
|
4154
1347
|
}
|
|
4155
|
-
if (source.startsWith("<!--",
|
|
4156
|
-
|
|
4157
|
-
|
|
4158
|
-
if (offset < tokenEnd2) {
|
|
4159
|
-
return void 0;
|
|
4160
|
-
}
|
|
4161
|
-
searchStart = tokenEnd2;
|
|
1348
|
+
if (source.startsWith("<!--", nextStart)) {
|
|
1349
|
+
index = source.indexOf("-->", nextStart + 4);
|
|
1350
|
+
index = index === -1 ? source.length : index + 3;
|
|
4162
1351
|
continue;
|
|
4163
1352
|
}
|
|
4164
|
-
|
|
4165
|
-
|
|
4166
|
-
|
|
4167
|
-
if (offset < tokenEnd2) {
|
|
4168
|
-
return void 0;
|
|
4169
|
-
}
|
|
4170
|
-
searchStart = tokenEnd2;
|
|
4171
|
-
continue;
|
|
1353
|
+
const nextEnd = findTagEnd(source, nextStart);
|
|
1354
|
+
if (nextEnd === -1) {
|
|
1355
|
+
break;
|
|
4172
1356
|
}
|
|
4173
|
-
|
|
4174
|
-
|
|
4175
|
-
|
|
4176
|
-
|
|
4177
|
-
|
|
1357
|
+
const nextTag = source.slice(nextStart, nextEnd + 1);
|
|
1358
|
+
const closingMatch = nextTag.match(/^<\s*\/\s*([A-Za-z_][A-Za-z0-9_.:-]*)/);
|
|
1359
|
+
const openingMatch = nextTag.match(/^<\s*([A-Za-z_][A-Za-z0-9_.:-]*)/);
|
|
1360
|
+
if (closingMatch?.[1]?.toLowerCase() === tagName) {
|
|
1361
|
+
depth -= 1;
|
|
1362
|
+
if (depth === 0) {
|
|
1363
|
+
return nextEnd + 1;
|
|
4178
1364
|
}
|
|
4179
|
-
|
|
4180
|
-
|
|
4181
|
-
}
|
|
4182
|
-
const tagEnd = findTagEnd3(source, start + 1);
|
|
4183
|
-
const contentEnd = tagEnd ?? source.length;
|
|
4184
|
-
const tokenEnd = tagEnd === void 0 ? source.length : tagEnd + 1;
|
|
4185
|
-
if (offset < tokenEnd) {
|
|
4186
|
-
return parseTag(source, start, contentEnd, tokenEnd);
|
|
4187
|
-
}
|
|
4188
|
-
if (tagEnd === void 0) {
|
|
4189
|
-
return void 0;
|
|
1365
|
+
} else if (openingMatch?.[1]?.toLowerCase() === tagName && !/\/\s*>$/.test(nextTag)) {
|
|
1366
|
+
depth += 1;
|
|
4190
1367
|
}
|
|
4191
|
-
|
|
1368
|
+
index = nextEnd + 1;
|
|
4192
1369
|
}
|
|
4193
|
-
return
|
|
4194
|
-
}
|
|
4195
|
-
function findParameter(definition, name) {
|
|
4196
|
-
return definition.parameters.find(
|
|
4197
|
-
(parameter) => parameter.name === name || parameter.aliases?.includes(name) === true
|
|
4198
|
-
);
|
|
1370
|
+
return tagEnd + 1;
|
|
4199
1371
|
}
|
|
4200
|
-
function
|
|
4201
|
-
|
|
1372
|
+
function createLens(model, start, end, title, action) {
|
|
1373
|
+
const startPosition = model.getPositionAt(start);
|
|
1374
|
+
const endPosition = model.getPositionAt(end);
|
|
1375
|
+
return {
|
|
1376
|
+
range: {
|
|
1377
|
+
startLineNumber: startPosition.lineNumber,
|
|
1378
|
+
startColumn: startPosition.column,
|
|
1379
|
+
endLineNumber: endPosition.lineNumber,
|
|
1380
|
+
endColumn: endPosition.column
|
|
1381
|
+
},
|
|
1382
|
+
command: {
|
|
1383
|
+
id: CODE_LENS_COMMAND,
|
|
1384
|
+
title,
|
|
1385
|
+
arguments: [action]
|
|
1386
|
+
}
|
|
1387
|
+
};
|
|
4202
1388
|
}
|
|
4203
|
-
function
|
|
4204
|
-
const
|
|
4205
|
-
|
|
4206
|
-
|
|
4207
|
-
|
|
4208
|
-
|
|
4209
|
-
|
|
4210
|
-
|
|
4211
|
-
|
|
4212
|
-
|
|
4213
|
-
|
|
4214
|
-
|
|
4215
|
-
|
|
4216
|
-
|
|
4217
|
-
|
|
4218
|
-
|
|
4219
|
-
|
|
4220
|
-
|
|
4221
|
-
|
|
4222
|
-
|
|
4223
|
-
|
|
4224
|
-
|
|
4225
|
-
|
|
4226
|
-
|
|
4227
|
-
|
|
4228
|
-
|
|
4229
|
-
|
|
1389
|
+
function registerSsmlCodeLens(monaco, editor, onOpenPopover) {
|
|
1390
|
+
const provider = {
|
|
1391
|
+
provideCodeLenses(model) {
|
|
1392
|
+
const source = model.getValue();
|
|
1393
|
+
const lenses = [];
|
|
1394
|
+
let index = 0;
|
|
1395
|
+
while (index < source.length) {
|
|
1396
|
+
const tagStart = source.indexOf("<", index);
|
|
1397
|
+
if (tagStart === -1) {
|
|
1398
|
+
break;
|
|
1399
|
+
}
|
|
1400
|
+
if (source.startsWith("<!--", tagStart)) {
|
|
1401
|
+
index = source.indexOf("-->", tagStart + 4);
|
|
1402
|
+
index = index === -1 ? source.length : index + 3;
|
|
1403
|
+
continue;
|
|
1404
|
+
}
|
|
1405
|
+
const tagEnd = findTagEnd(source, tagStart);
|
|
1406
|
+
if (tagEnd === -1) {
|
|
1407
|
+
break;
|
|
1408
|
+
}
|
|
1409
|
+
const tag = source.slice(tagStart, tagEnd + 1);
|
|
1410
|
+
const tagName = tag.match(/^<\s*(prosody|break)\b/i)?.[1]?.toLowerCase();
|
|
1411
|
+
index = tagEnd + 1;
|
|
1412
|
+
if (!tagName) {
|
|
1413
|
+
continue;
|
|
1414
|
+
}
|
|
1415
|
+
const tagRange = getTagRange(tagStart, tagEnd + 1);
|
|
1416
|
+
const elementEnd = getElementEnd(source, tagName, tagEnd);
|
|
1417
|
+
const elementRange = { start: tagStart, end: elementEnd };
|
|
1418
|
+
if (tagName === "prosody") {
|
|
1419
|
+
lenses.push(
|
|
1420
|
+
createLens(
|
|
1421
|
+
model,
|
|
1422
|
+
tagStart,
|
|
1423
|
+
tagEnd + 1,
|
|
1424
|
+
`\u26A1 Rate: ${getAttributeValue(tag, "rate") ?? "default"} (Click to edit)`,
|
|
1425
|
+
{ type: "attribute", insertionId: "rate", attributeName: "rate", tagRange }
|
|
1426
|
+
),
|
|
1427
|
+
createLens(
|
|
1428
|
+
model,
|
|
1429
|
+
tagStart,
|
|
1430
|
+
tagEnd + 1,
|
|
1431
|
+
`\u26A1 Pitch: ${getAttributeValue(tag, "pitch") ?? "default"} (Click to edit)`,
|
|
1432
|
+
{ type: "attribute", insertionId: "pitch", attributeName: "pitch", tagRange }
|
|
1433
|
+
),
|
|
1434
|
+
createLens(model, tagStart, tagEnd + 1, "Unwrap", {
|
|
1435
|
+
type: "unwrap",
|
|
1436
|
+
tagRange,
|
|
1437
|
+
elementRange
|
|
1438
|
+
})
|
|
1439
|
+
);
|
|
1440
|
+
} else if (/\/\s*>$/.test(tag)) {
|
|
1441
|
+
lenses.push(
|
|
1442
|
+
createLens(
|
|
1443
|
+
model,
|
|
1444
|
+
tagStart,
|
|
1445
|
+
tagEnd + 1,
|
|
1446
|
+
`\u26A1 Time: ${getAttributeValue(tag, "time") ?? "default"} (Click to edit)`,
|
|
1447
|
+
{ type: "attribute", insertionId: "break", attributeName: "time", tagRange }
|
|
1448
|
+
),
|
|
1449
|
+
createLens(model, tagStart, tagEnd + 1, "Delete", {
|
|
1450
|
+
type: "delete",
|
|
1451
|
+
tagRange,
|
|
1452
|
+
elementRange
|
|
1453
|
+
})
|
|
1454
|
+
);
|
|
1455
|
+
}
|
|
4230
1456
|
}
|
|
4231
|
-
return {
|
|
4232
|
-
kind: "parameter",
|
|
4233
|
-
tagName: tag.name,
|
|
4234
|
-
isClosingTag: tag.closing,
|
|
4235
|
-
definition,
|
|
4236
|
-
parameter,
|
|
4237
|
-
range: toRange(source, attribute.name)
|
|
4238
|
-
};
|
|
1457
|
+
return { lenses, dispose: () => void 0 };
|
|
4239
1458
|
}
|
|
4240
|
-
|
|
4241
|
-
|
|
4242
|
-
|
|
4243
|
-
|
|
4244
|
-
|
|
4245
|
-
|
|
4246
|
-
kind: "parameter-value",
|
|
4247
|
-
tagName: tag.name,
|
|
4248
|
-
isClosingTag: tag.closing,
|
|
4249
|
-
definition,
|
|
4250
|
-
parameter,
|
|
4251
|
-
range: toRange(source, attribute.value)
|
|
4252
|
-
};
|
|
1459
|
+
};
|
|
1460
|
+
const disposable = monaco.languages.registerCodeLensProvider("xml", provider);
|
|
1461
|
+
const commandHandler = (_accessor, ...args) => {
|
|
1462
|
+
const action = args[0];
|
|
1463
|
+
if (action && typeof action === "object" && "type" in action) {
|
|
1464
|
+
onOpenPopover(action);
|
|
4253
1465
|
}
|
|
4254
|
-
}
|
|
4255
|
-
|
|
4256
|
-
|
|
4257
|
-
|
|
4258
|
-
|
|
4259
|
-
|
|
4260
|
-
|
|
4261
|
-
|
|
4262
|
-
|
|
4263
|
-
const values = parameter.values && parameter.values.length > 0 ? ` ${SSML_HOVER_COPY[locale].allowedValues}: ${parameter.values.map(code).join(", ")}.` : "";
|
|
4264
|
-
const example = parameter.example ? ` ${SSML_HOVER_COPY[locale].example}: ${code(parameter.example)}.` : "";
|
|
4265
|
-
return `- ${code(parameter.name)}: ${description}${values}${example}`;
|
|
4266
|
-
}
|
|
4267
|
-
function formatSsmlHover(target, locale = "en") {
|
|
4268
|
-
const localizedTag = SSML_HOVER_COPY[locale].tags[target.definition.name];
|
|
4269
|
-
const tagTitle = localizedTag?.title ?? target.definition.name;
|
|
4270
|
-
const tagDescription = localizedTag?.description ?? target.definition.description;
|
|
4271
|
-
const tagSyntax = target.isClosingTag ? `</${target.tagName}>` : `<${target.tagName}>`;
|
|
4272
|
-
const lines = [`### ${code(tagSyntax)}`, "", `**${tagTitle}**`, "", tagDescription];
|
|
4273
|
-
if (target.parameter) {
|
|
4274
|
-
const localizedParameter = localizedTag?.parameters[target.parameter.name];
|
|
4275
|
-
const parameterTitle = localizedParameter?.title ?? target.parameter.name;
|
|
4276
|
-
const parameterDescription = localizedParameter?.description ?? target.parameter.description;
|
|
4277
|
-
lines.push("", `**${SSML_HOVER_COPY[locale].parameterHeading} ${code(parameterTitle)}**`, "", parameterDescription);
|
|
4278
|
-
if (target.parameter.values && target.parameter.values.length > 0) {
|
|
4279
|
-
lines.push("", `${SSML_HOVER_COPY[locale].allowedValues}: ${target.parameter.values.map(code).join(", ")}.`);
|
|
1466
|
+
};
|
|
1467
|
+
const commandDisposable = typeof monaco.editor?.registerCommand === "function" ? monaco.editor.registerCommand(CODE_LENS_COMMAND, commandHandler) : typeof monaco.registerCommand === "function" ? monaco.registerCommand(CODE_LENS_COMMAND, commandHandler) : editor.addAction({
|
|
1468
|
+
id: CODE_LENS_COMMAND,
|
|
1469
|
+
label: "SSML CodeLens",
|
|
1470
|
+
run: (_editor, ...args) => {
|
|
1471
|
+
const action = args[0];
|
|
1472
|
+
if (action && typeof action === "object" && "type" in action) {
|
|
1473
|
+
onOpenPopover(action);
|
|
1474
|
+
}
|
|
4280
1475
|
}
|
|
4281
|
-
|
|
4282
|
-
|
|
1476
|
+
});
|
|
1477
|
+
return {
|
|
1478
|
+
dispose: () => {
|
|
1479
|
+
commandDisposable.dispose();
|
|
1480
|
+
disposable.dispose();
|
|
4283
1481
|
}
|
|
4284
|
-
}
|
|
4285
|
-
lines.push(
|
|
4286
|
-
"",
|
|
4287
|
-
`**${SSML_HOVER_COPY[locale].parametersHeading}**`,
|
|
4288
|
-
"",
|
|
4289
|
-
...target.definition.parameters.map((parameter) => formatParameter(parameter, target.definition.name, locale))
|
|
4290
|
-
);
|
|
4291
|
-
} else {
|
|
4292
|
-
lines.push("", SSML_HOVER_COPY[locale].noParameters);
|
|
4293
|
-
}
|
|
4294
|
-
return lines.join("\n");
|
|
1482
|
+
};
|
|
4295
1483
|
}
|
|
4296
1484
|
|
|
4297
1485
|
// packages/ssml-editor-react/src/hooks/useSsmlMonaco.ts
|
|
@@ -4395,8 +1583,11 @@ function useSsmlMonaco({
|
|
|
4395
1583
|
language,
|
|
4396
1584
|
text,
|
|
4397
1585
|
decorationsVisible,
|
|
1586
|
+
enableCodeLens,
|
|
4398
1587
|
getOuterVoiceName,
|
|
1588
|
+
onOpenPopover,
|
|
4399
1589
|
onSelectionOverlayChange,
|
|
1590
|
+
onActiveTagsChange,
|
|
4400
1591
|
onSyntaxErrorChange
|
|
4401
1592
|
}) {
|
|
4402
1593
|
const internalEditorRef = useRef2(null);
|
|
@@ -4404,22 +1595,30 @@ function useSsmlMonaco({
|
|
|
4404
1595
|
const monacoRef = useRef2(null);
|
|
4405
1596
|
const completionProviderRef = useRef2(null);
|
|
4406
1597
|
const codeActionProviderRef = useRef2(null);
|
|
1598
|
+
const codeLensProviderRef = useRef2(null);
|
|
4407
1599
|
const releaseHoverProviderRef = useRef2(null);
|
|
4408
1600
|
const selectionChangeRef = useRef2(null);
|
|
1601
|
+
const cursorPositionChangeRef = useRef2(null);
|
|
4409
1602
|
const diagnosticsChangeRef = useRef2(null);
|
|
4410
1603
|
const diagnosticsTimeoutRef = useRef2(null);
|
|
4411
1604
|
const selectionLayoutDisposablesRef = useRef2([]);
|
|
4412
1605
|
const inlineDecorationIdsRef = useRef2([]);
|
|
4413
1606
|
const languageRef = useRef2(language);
|
|
4414
1607
|
const decorationsVisibleRef = useRef2(decorationsVisible);
|
|
1608
|
+
const enableCodeLensRef = useRef2(enableCodeLens);
|
|
4415
1609
|
const getOuterVoiceNameRef = useRef2(getOuterVoiceName);
|
|
4416
1610
|
const onSelectionOverlayChangeRef = useRef2(onSelectionOverlayChange);
|
|
1611
|
+
const onActiveTagsChangeRef = useRef2(onActiveTagsChange);
|
|
4417
1612
|
const onSyntaxErrorChangeRef = useRef2(onSyntaxErrorChange);
|
|
1613
|
+
const onOpenPopoverRef = useRef2(onOpenPopover);
|
|
4418
1614
|
languageRef.current = language;
|
|
4419
1615
|
decorationsVisibleRef.current = decorationsVisible;
|
|
1616
|
+
enableCodeLensRef.current = enableCodeLens;
|
|
4420
1617
|
getOuterVoiceNameRef.current = getOuterVoiceName;
|
|
4421
1618
|
onSelectionOverlayChangeRef.current = onSelectionOverlayChange;
|
|
1619
|
+
onActiveTagsChangeRef.current = onActiveTagsChange;
|
|
4422
1620
|
onSyntaxErrorChangeRef.current = onSyntaxErrorChange;
|
|
1621
|
+
onOpenPopoverRef.current = onOpenPopover;
|
|
4423
1622
|
const runSsmlDiagnostics = useCallback2((editor, monaco) => {
|
|
4424
1623
|
const model = editor.getModel();
|
|
4425
1624
|
if (!model) {
|
|
@@ -4448,6 +1647,15 @@ function useSsmlMonaco({
|
|
|
4448
1647
|
diagnosticsChangeRef.current?.dispose();
|
|
4449
1648
|
diagnosticsChangeRef.current = null;
|
|
4450
1649
|
}, []);
|
|
1650
|
+
const syncActiveTags = useCallback2((editor) => {
|
|
1651
|
+
const model = editor.getModel();
|
|
1652
|
+
const position = editor.getPosition();
|
|
1653
|
+
if (!model || !position) {
|
|
1654
|
+
onActiveTagsChangeRef.current(/* @__PURE__ */ new Set());
|
|
1655
|
+
return;
|
|
1656
|
+
}
|
|
1657
|
+
onActiveTagsChangeRef.current(findActiveSsmlTags(model.getValue(), model.getOffsetAt(position)));
|
|
1658
|
+
}, []);
|
|
4451
1659
|
const disposeMonacoResources = useCallback2(() => {
|
|
4452
1660
|
clearSsmlDiagnosticsResources();
|
|
4453
1661
|
const model = editorRef.current?.getModel();
|
|
@@ -4457,10 +1665,14 @@ function useSsmlMonaco({
|
|
|
4457
1665
|
}
|
|
4458
1666
|
selectionChangeRef.current?.dispose();
|
|
4459
1667
|
selectionChangeRef.current = null;
|
|
1668
|
+
cursorPositionChangeRef.current?.dispose();
|
|
1669
|
+
cursorPositionChangeRef.current = null;
|
|
4460
1670
|
completionProviderRef.current?.dispose();
|
|
4461
1671
|
completionProviderRef.current = null;
|
|
4462
1672
|
codeActionProviderRef.current?.dispose();
|
|
4463
1673
|
codeActionProviderRef.current = null;
|
|
1674
|
+
codeLensProviderRef.current?.dispose();
|
|
1675
|
+
codeLensProviderRef.current = null;
|
|
4464
1676
|
for (const disposable of selectionLayoutDisposablesRef.current) {
|
|
4465
1677
|
disposable.dispose();
|
|
4466
1678
|
}
|
|
@@ -4478,6 +1690,9 @@ function useSsmlMonaco({
|
|
|
4478
1690
|
selectionChangeRef.current = editor.onDidChangeCursorSelection(() => {
|
|
4479
1691
|
onSelectionOverlayChangeRef.current(editor, true);
|
|
4480
1692
|
});
|
|
1693
|
+
cursorPositionChangeRef.current = editor.onDidChangeCursorPosition(() => {
|
|
1694
|
+
syncActiveTags(editor);
|
|
1695
|
+
});
|
|
4481
1696
|
diagnosticsChangeRef.current = editor.onDidChangeModelContent(() => {
|
|
4482
1697
|
const model2 = editor.getModel();
|
|
4483
1698
|
if (model2) {
|
|
@@ -4489,6 +1704,7 @@ function useSsmlMonaco({
|
|
|
4489
1704
|
inlineDecorationIdsRef.current
|
|
4490
1705
|
);
|
|
4491
1706
|
}
|
|
1707
|
+
syncActiveTags(editor);
|
|
4492
1708
|
scheduleSsmlDiagnostics(editor, monaco);
|
|
4493
1709
|
});
|
|
4494
1710
|
selectionLayoutDisposablesRef.current = [
|
|
@@ -4501,6 +1717,13 @@ function useSsmlMonaco({
|
|
|
4501
1717
|
model: editor.getModel()
|
|
4502
1718
|
});
|
|
4503
1719
|
codeActionProviderRef.current = registerSsmlCodeActions(monaco);
|
|
1720
|
+
if (enableCodeLensRef.current) {
|
|
1721
|
+
codeLensProviderRef.current = registerSsmlCodeLens(
|
|
1722
|
+
monaco,
|
|
1723
|
+
editor,
|
|
1724
|
+
(action) => onOpenPopoverRef.current(action)
|
|
1725
|
+
);
|
|
1726
|
+
}
|
|
4504
1727
|
releaseHoverProviderRef.current = acquireSsmlHoverProvider(monaco, languageRef.current);
|
|
4505
1728
|
runSsmlDiagnostics(editor, monaco);
|
|
4506
1729
|
const model = editor.getModel();
|
|
@@ -4514,9 +1737,19 @@ function useSsmlMonaco({
|
|
|
4514
1737
|
);
|
|
4515
1738
|
}
|
|
4516
1739
|
onSelectionOverlayChangeRef.current(editor, true);
|
|
1740
|
+
syncActiveTags(editor);
|
|
4517
1741
|
},
|
|
4518
|
-
[disposeMonacoResources, editorRef, runSsmlDiagnostics, scheduleSsmlDiagnostics]
|
|
1742
|
+
[disposeMonacoResources, editorRef, runSsmlDiagnostics, scheduleSsmlDiagnostics, syncActiveTags]
|
|
4519
1743
|
);
|
|
1744
|
+
useEffect2(() => {
|
|
1745
|
+
const editor = editorRef.current;
|
|
1746
|
+
const monaco = monacoRef.current;
|
|
1747
|
+
if (!editor || !monaco) {
|
|
1748
|
+
return;
|
|
1749
|
+
}
|
|
1750
|
+
codeLensProviderRef.current?.dispose();
|
|
1751
|
+
codeLensProviderRef.current = enableCodeLens ? registerSsmlCodeLens(monaco, editor, (action) => onOpenPopoverRef.current(action)) : null;
|
|
1752
|
+
}, [editorRef, enableCodeLens]);
|
|
4520
1753
|
useEffect2(() => {
|
|
4521
1754
|
const monaco = monacoRef.current;
|
|
4522
1755
|
if (!monaco) {
|
|
@@ -4903,6 +2136,8 @@ var STYLE_CSS = `
|
|
|
4903
2136
|
--ssml-editor-border: #d1d5db;
|
|
4904
2137
|
--ssml-editor-control-bg: #f9fafb;
|
|
4905
2138
|
--ssml-editor-control-border: #9ca3af;
|
|
2139
|
+
--ssml-editor-active-bg: #dbeafe;
|
|
2140
|
+
--ssml-editor-active-border: #2563eb;
|
|
4906
2141
|
--ssml-editor-preview-bg: #f3f4f6;
|
|
4907
2142
|
--ssml-editor-error: #b91c1c;
|
|
4908
2143
|
--ssml-editor-error-bg: #fef2f2;
|
|
@@ -4920,6 +2155,8 @@ var STYLE_CSS = `
|
|
|
4920
2155
|
--ssml-editor-border: #374151;
|
|
4921
2156
|
--ssml-editor-control-bg: #111827;
|
|
4922
2157
|
--ssml-editor-control-border: #4b5563;
|
|
2158
|
+
--ssml-editor-active-bg: #1e3a8a;
|
|
2159
|
+
--ssml-editor-active-border: #60a5fa;
|
|
4923
2160
|
--ssml-editor-preview-bg: #111827;
|
|
4924
2161
|
--ssml-editor-error: #fca5a5;
|
|
4925
2162
|
--ssml-editor-error-bg: #450a0a;
|
|
@@ -5033,6 +2270,7 @@ var SsmlEditor = forwardRef(function SsmlEditor2({
|
|
|
5033
2270
|
showToolbarIcons = true,
|
|
5034
2271
|
showToolbarLabels = false,
|
|
5035
2272
|
showDecorations = false,
|
|
2273
|
+
enableCodeLens = true,
|
|
5036
2274
|
buttonVisibility,
|
|
5037
2275
|
editorOptions,
|
|
5038
2276
|
settings,
|
|
@@ -5139,6 +2377,7 @@ var SsmlEditor = forwardRef(function SsmlEditor2({
|
|
|
5139
2377
|
editorRef,
|
|
5140
2378
|
text,
|
|
5141
2379
|
selectionOverlay,
|
|
2380
|
+
activeTags,
|
|
5142
2381
|
isDarkTheme,
|
|
5143
2382
|
decorationsVisible,
|
|
5144
2383
|
setDecorationsVisible,
|
|
@@ -5159,10 +2398,12 @@ var SsmlEditor = forwardRef(function SsmlEditor2({
|
|
|
5159
2398
|
previewSelection,
|
|
5160
2399
|
canPreviewSelection,
|
|
5161
2400
|
refreshSelectionOverlay,
|
|
2401
|
+
updateActiveTags,
|
|
5162
2402
|
getSelectedSsml: getSelectedSsml2,
|
|
5163
2403
|
getCurrentLineSsml: getCurrentLineSsml2,
|
|
5164
2404
|
getFullSsml,
|
|
5165
2405
|
getOuterVoiceName,
|
|
2406
|
+
handleCodeLensAction,
|
|
5166
2407
|
openPopoverId,
|
|
5167
2408
|
popoverVoiceName,
|
|
5168
2409
|
popoverPosition,
|
|
@@ -5187,7 +2428,10 @@ var SsmlEditor = forwardRef(function SsmlEditor2({
|
|
|
5187
2428
|
decorationsVisible,
|
|
5188
2429
|
getOuterVoiceName,
|
|
5189
2430
|
onSelectionOverlayChange: refreshSelectionOverlay,
|
|
5190
|
-
|
|
2431
|
+
onActiveTagsChange: updateActiveTags,
|
|
2432
|
+
onSyntaxErrorChange: setSyntaxError,
|
|
2433
|
+
enableCodeLens,
|
|
2434
|
+
onOpenPopover: handleCodeLensAction
|
|
5191
2435
|
});
|
|
5192
2436
|
useImperativeHandle(
|
|
5193
2437
|
ref,
|
|
@@ -5202,12 +2446,13 @@ var SsmlEditor = forwardRef(function SsmlEditor2({
|
|
|
5202
2446
|
const isTimingPopover = insertion.tagName !== void 0 && TIMING_POPOVER_TAGS.has(insertion.tagName);
|
|
5203
2447
|
const isProsodyPopover = insertion.tagName !== void 0 && PROSODY_POPOVER_TAGS.has(insertion.tagName);
|
|
5204
2448
|
const isTextPopover = insertion.tagName !== void 0 && TEXT_POPOVER_TAGS.has(insertion.tagName);
|
|
2449
|
+
const insertionButtonStyle = insertion.tagName && activeTags.has(insertion.tagName.toLowerCase()) ? { ...toolbarButtonStyle, ...editorStyles.toolbarButtonActive } : toolbarButtonStyle;
|
|
5205
2450
|
const props = {
|
|
5206
2451
|
language,
|
|
5207
2452
|
isDarkTheme,
|
|
5208
2453
|
showToolbarIcons,
|
|
5209
2454
|
showToolbarText,
|
|
5210
|
-
toolbarButtonStyle,
|
|
2455
|
+
toolbarButtonStyle: insertionButtonStyle,
|
|
5211
2456
|
emptyOptionsMessage: copy.noAvailableOptions,
|
|
5212
2457
|
isReadOnly,
|
|
5213
2458
|
openPopoverId,
|
|
@@ -5464,6 +2709,8 @@ export {
|
|
|
5464
2709
|
SSML_HOVER_COPY,
|
|
5465
2710
|
SSML_INSERTIONS,
|
|
5466
2711
|
SsmlEditor,
|
|
5467
|
-
createSsmlEditorInsertionDefinition
|
|
2712
|
+
createSsmlEditorInsertionDefinition,
|
|
2713
|
+
registerSsmlCodeLens,
|
|
2714
|
+
updateTagAttribute
|
|
5468
2715
|
};
|
|
5469
2716
|
//# sourceMappingURL=react.mjs.map
|