ssml-builder-js 2.13.0 → 2.15.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 +12 -2
- package/dist/{chunk-LCTE26LS.mjs → chunk-BDY2Q2JL.mjs} +2 -2
- package/dist/{chunk-25LOR4AJ.mjs → chunk-FXUM45ZY.mjs} +402 -169
- package/dist/chunk-FXUM45ZY.mjs.map +1 -0
- package/dist/{chunk-CZ2F3TET.mjs → chunk-WXFLUCLR.mjs} +227 -9
- package/dist/chunk-WXFLUCLR.mjs.map +1 -0
- package/dist/core.d.mts +65 -17
- package/dist/core.d.ts +65 -17
- package/dist/core.js +401 -166
- package/dist/core.js.map +1 -1
- package/dist/core.mjs +5 -1
- package/dist/elements.js +101 -8
- package/dist/elements.js.map +1 -1
- package/dist/elements.mjs +2 -2
- package/dist/{index.d-Xbr6ZWnK.d.mts → index.d-8BvkB9gz.d.mts} +40 -2
- package/dist/{index.d-Xbr6ZWnK.d.ts → index.d-8BvkB9gz.d.ts} +40 -2
- package/dist/index.d.mts +170 -18
- package/dist/index.d.ts +170 -18
- package/dist/index.js +1512 -489
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +612 -47
- package/dist/index.mjs.map +1 -1
- package/dist/react.d.mts +15 -2
- package/dist/react.d.ts +15 -2
- package/dist/react.js +204 -23
- package/dist/react.js.map +1 -1
- package/dist/react.mjs +105 -17
- package/dist/react.mjs.map +1 -1
- package/package.json +1 -1
- package/dist/chunk-25LOR4AJ.mjs.map +0 -1
- package/dist/chunk-CZ2F3TET.mjs.map +0 -1
- /package/dist/{chunk-LCTE26LS.mjs.map → chunk-BDY2Q2JL.mjs.map} +0 -0
package/dist/react.mjs
CHANGED
|
@@ -42,13 +42,13 @@ import {
|
|
|
42
42
|
resolveExpressAsStyles,
|
|
43
43
|
updateEditableText,
|
|
44
44
|
updateTagAttribute
|
|
45
|
-
} from "./chunk-
|
|
45
|
+
} from "./chunk-BDY2Q2JL.mjs";
|
|
46
46
|
import {
|
|
47
47
|
buildPartialSsml,
|
|
48
48
|
buildSsml,
|
|
49
49
|
validateAzureSsml,
|
|
50
50
|
validateSsml
|
|
51
|
-
} from "./chunk-
|
|
51
|
+
} from "./chunk-WXFLUCLR.mjs";
|
|
52
52
|
import "./chunk-6S5ODO6A.mjs";
|
|
53
53
|
|
|
54
54
|
// packages/ssml-editor-react/src/SsmlEditor.tsx
|
|
@@ -1960,13 +1960,65 @@ function localizedElementLabel(element, locale) {
|
|
|
1960
1960
|
function filteredVoices(voiceCatalog, locale, region, style) {
|
|
1961
1961
|
return (voiceCatalog ?? []).filter((voice) => {
|
|
1962
1962
|
if (locale && voice.locale.toLowerCase() !== locale.toLowerCase()) return false;
|
|
1963
|
-
|
|
1963
|
+
const regions = [voice.region, ...voice.regions ?? []].filter(
|
|
1964
|
+
(candidate) => Boolean(candidate)
|
|
1965
|
+
);
|
|
1966
|
+
if (region && regions.length > 0 && !regions.some((candidate) => candidate.toLowerCase() === region.toLowerCase()))
|
|
1967
|
+
return false;
|
|
1964
1968
|
if (style && !voice.styles?.some((candidate) => candidate.toLowerCase() === style.toLowerCase())) return false;
|
|
1965
1969
|
return true;
|
|
1966
1970
|
});
|
|
1967
1971
|
}
|
|
1968
|
-
function
|
|
1972
|
+
function VoiceCapabilityMatrix({
|
|
1973
|
+
voice,
|
|
1974
|
+
locale
|
|
1975
|
+
}) {
|
|
1976
|
+
const status = voice.status ?? (voice.preview ? "preview" : void 0);
|
|
1977
|
+
return /* @__PURE__ */ React.createElement("div", { className: "ssml-editor-voice-capabilities", "data-voice-capabilities": "" }, /* @__PURE__ */ React.createElement("div", null, locale === "ja" ? "\u30B9\u30C6\u30FC\u30BF\u30B9" : "Status", ": ", status?.toUpperCase() ?? (locale === "ja" ? "GA" : "GA"), status === "preview" || status === "deprecated" ? /* @__PURE__ */ React.createElement("span", { role: "status", "aria-label": status, className: "ssml-editor-voice-warning-badge" }, status === "preview" ? "\u26A0 Preview" : "\u26A0 Deprecated") : null), (voice.regions?.length || voice.region) && /* @__PURE__ */ React.createElement("div", null, locale === "ja" ? "\u30EA\u30FC\u30B8\u30E7\u30F3" : "Regions", ":", " ", [...voice.regions ?? [], ...voice.region ? [voice.region] : []].filter((region, index, all) => all.indexOf(region) === index).join(", ")), voice.supportedTags && voice.supportedTags.length > 0 && /* @__PURE__ */ React.createElement("div", null, locale === "ja" ? "\u5BFE\u5FDC\u30BF\u30B0" : "Supported tags", ": ", voice.supportedTags.join(", ")), voice.unsupportedTags && voice.unsupportedTags.length > 0 && /* @__PURE__ */ React.createElement("div", { className: "ssml-editor-voice-unsupported" }, locale === "ja" ? "\u975E\u5BFE\u5FDC\u30BF\u30B0" : "Unsupported tags", ": ", voice.unsupportedTags.join(", ")));
|
|
1978
|
+
}
|
|
1979
|
+
function diagnosticMatchesElement(diagnostic, element) {
|
|
1980
|
+
const name = elementLabel(element).toLowerCase().replace("expressas", "mstts:express-as");
|
|
1981
|
+
if (diagnostic.code === "azure-unsupported-style") return name === "mstts:express-as" || name === "express-as";
|
|
1982
|
+
if (diagnostic.code === "azure-unsupported-tag-for-voice") {
|
|
1983
|
+
return diagnostic.message.toLowerCase().includes(`<${name}>`) || diagnostic.message.toLowerCase().includes(`<${name.replace("mstts:", "")}>`);
|
|
1984
|
+
}
|
|
1985
|
+
if (diagnostic.code === "azure-locale-mismatch" || diagnostic.code === "azure-unsupported-model-for-voice")
|
|
1986
|
+
return name === "voice" || name === "mstts:turn";
|
|
1987
|
+
return false;
|
|
1988
|
+
}
|
|
1989
|
+
function elementWarnings(diagnostics, element) {
|
|
1990
|
+
return diagnostics.filter((diagnostic) => diagnosticMatchesElement(diagnostic, element));
|
|
1991
|
+
}
|
|
1992
|
+
function fieldWarnings(diagnostics, element, field) {
|
|
1993
|
+
return elementWarnings(diagnostics, element).filter((diagnostic) => {
|
|
1994
|
+
if (diagnostic.code === "azure-unsupported-style") return field.key === "style";
|
|
1995
|
+
return field.key === "name" || field.key === "voice";
|
|
1996
|
+
});
|
|
1997
|
+
}
|
|
1998
|
+
function WarningBadge({ messages }) {
|
|
1999
|
+
if (messages.length === 0) return null;
|
|
1969
2000
|
return /* @__PURE__ */ React.createElement(
|
|
2001
|
+
"span",
|
|
2002
|
+
{
|
|
2003
|
+
role: "status",
|
|
2004
|
+
"aria-label": messages.map((message) => message.message).join(" "),
|
|
2005
|
+
title: messages.map((message) => message.message).join(" "),
|
|
2006
|
+
"data-ssml-warning-badge": "",
|
|
2007
|
+
"data-testid": "ssml-editor-warning-badge",
|
|
2008
|
+
className: "ssml-editor-warning-badge"
|
|
2009
|
+
},
|
|
2010
|
+
"\u26A0"
|
|
2011
|
+
);
|
|
2012
|
+
}
|
|
2013
|
+
function DefaultVoiceSelector({
|
|
2014
|
+
value,
|
|
2015
|
+
voices,
|
|
2016
|
+
selectedVoice,
|
|
2017
|
+
readOnly,
|
|
2018
|
+
locale,
|
|
2019
|
+
onChange
|
|
2020
|
+
}) {
|
|
2021
|
+
return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(
|
|
1970
2022
|
"select",
|
|
1971
2023
|
{
|
|
1972
2024
|
"aria-label": locale === "ja" ? "\u97F3\u58F0" : "Voice",
|
|
@@ -1976,7 +2028,7 @@ function DefaultVoiceSelector({ value, voices, readOnly, locale, onChange }) {
|
|
|
1976
2028
|
},
|
|
1977
2029
|
/* @__PURE__ */ React.createElement("option", { value: "" }, locale === "ja" ? "\u97F3\u58F0\u3092\u9078\u629E" : "Select a voice"),
|
|
1978
2030
|
voices.map((voice) => /* @__PURE__ */ React.createElement("option", { key: voice.name, value: voice.name }, voice.name, voice.preview || voice.status === "preview" ? " (preview)" : ""))
|
|
1979
|
-
);
|
|
2031
|
+
), selectedVoice ? /* @__PURE__ */ React.createElement(VoiceCapabilityMatrix, { voice: selectedVoice, locale }) : null);
|
|
1980
2032
|
}
|
|
1981
2033
|
function VisualElementInspector({
|
|
1982
2034
|
document: document2,
|
|
@@ -1990,15 +2042,19 @@ function VisualElementInspector({
|
|
|
1990
2042
|
voiceCatalog,
|
|
1991
2043
|
voiceLocale,
|
|
1992
2044
|
voiceRegion,
|
|
1993
|
-
voiceStyle
|
|
2045
|
+
voiceStyle,
|
|
2046
|
+
diagnostics
|
|
1994
2047
|
}) {
|
|
1995
2048
|
if (customInspector) {
|
|
1996
2049
|
return /* @__PURE__ */ React.createElement(React.Fragment, null, customInspector({ document: document2, element, path, readOnly, onChange: commit, locale }));
|
|
1997
2050
|
}
|
|
1998
2051
|
const fields = getElementFields(element);
|
|
1999
2052
|
const availableVoices = filteredVoices(voiceCatalog, voiceLocale, voiceRegion, voiceStyle);
|
|
2053
|
+
const selectedVoice = voiceCatalog?.find(
|
|
2054
|
+
(voice) => voice.name === (element.type === "voice" ? element.name : void 0)
|
|
2055
|
+
);
|
|
2000
2056
|
const renderSelector = renderVoiceSelector ?? DefaultVoiceSelector;
|
|
2001
|
-
return /* @__PURE__ */ React.createElement("fieldset", null, /* @__PURE__ */ React.createElement("legend", null, `<${elementLabel(element)}
|
|
2057
|
+
return /* @__PURE__ */ React.createElement("fieldset", null, /* @__PURE__ */ React.createElement("legend", null, `<${elementLabel(element)}>`, " ", /* @__PURE__ */ React.createElement(WarningBadge, { messages: elementWarnings(diagnostics, element) })), fields.length === 0 ? /* @__PURE__ */ React.createElement("p", null, "This element is preserved in the visual tree. Edit its attributes in Code mode.") : fields.map((field) => {
|
|
2002
2058
|
const value = element[field.key];
|
|
2003
2059
|
const inputValue = value === void 0 ? "" : String(value);
|
|
2004
2060
|
const inputId = `ssml-visual-${field.key}`;
|
|
@@ -2035,9 +2091,10 @@ function VisualElementInspector({
|
|
|
2035
2091
|
speakerProfileId: "\u8A71\u8005\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB ID",
|
|
2036
2092
|
url: "\u97F3\u58F0\u5909\u63DB URL",
|
|
2037
2093
|
profile: "\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB"
|
|
2038
|
-
}[field.key] ?? field.label : field.label, field.key === "name" && elementLabel(element) === "voice" && voiceCatalog ? renderSelector({
|
|
2094
|
+
}[field.key] ?? field.label : field.label, /* @__PURE__ */ React.createElement(WarningBadge, { messages: fieldWarnings(diagnostics, element, field) }), field.key === "name" && elementLabel(element) === "voice" && voiceCatalog ? renderSelector({
|
|
2039
2095
|
value: inputValue,
|
|
2040
2096
|
voices: availableVoices,
|
|
2097
|
+
selectedVoice,
|
|
2041
2098
|
readOnly,
|
|
2042
2099
|
locale,
|
|
2043
2100
|
onChange: (value2) => commit(updateOptionalElementProperty(document2, path, field.key, value2))
|
|
@@ -2112,19 +2169,21 @@ function TreeNode({
|
|
|
2112
2169
|
node,
|
|
2113
2170
|
path,
|
|
2114
2171
|
selectedPath,
|
|
2115
|
-
onSelect
|
|
2172
|
+
onSelect,
|
|
2173
|
+
getWarnings
|
|
2116
2174
|
}) {
|
|
2117
2175
|
if (!isElement(node)) return null;
|
|
2118
2176
|
const name = elementLabel(node);
|
|
2119
2177
|
const isSelected = selectedPath?.join(".") === path.join(".");
|
|
2120
|
-
return /* @__PURE__ */ React.createElement("li", null, /* @__PURE__ */ React.createElement("button", { type: "button", "aria-current": isSelected ? "true" : void 0, onClick: () => onSelect(path) }, `<${name}
|
|
2178
|
+
return /* @__PURE__ */ React.createElement("li", null, /* @__PURE__ */ React.createElement("button", { type: "button", "aria-current": isSelected ? "true" : void 0, onClick: () => onSelect(path) }, `<${name}>`, /* @__PURE__ */ React.createElement(WarningBadge, { messages: getWarnings(node) })), (node.children ?? []).length > 0 && /* @__PURE__ */ React.createElement("ul", null, node.children?.map((child, index) => /* @__PURE__ */ React.createElement(
|
|
2121
2179
|
TreeNode,
|
|
2122
2180
|
{
|
|
2123
2181
|
key: `${path.join(".")}/${isElement(child) ? elementLabel(child) : JSON.stringify(child)}`,
|
|
2124
2182
|
node: child,
|
|
2125
2183
|
path: [...path, index],
|
|
2126
2184
|
selectedPath,
|
|
2127
|
-
onSelect
|
|
2185
|
+
onSelect,
|
|
2186
|
+
getWarnings
|
|
2128
2187
|
}
|
|
2129
2188
|
))));
|
|
2130
2189
|
}
|
|
@@ -2139,7 +2198,9 @@ function VisualSsmlEditor({
|
|
|
2139
2198
|
voiceCatalog,
|
|
2140
2199
|
voiceLocale,
|
|
2141
2200
|
voiceRegion,
|
|
2142
|
-
voiceStyle
|
|
2201
|
+
voiceStyle,
|
|
2202
|
+
voiceModel,
|
|
2203
|
+
model
|
|
2143
2204
|
}) {
|
|
2144
2205
|
const [selectedPath, setSelectedPath] = useState2(null);
|
|
2145
2206
|
const [selection, setSelection] = useState2({ start: 0, end: 0 });
|
|
@@ -2147,7 +2208,27 @@ function VisualSsmlEditor({
|
|
|
2147
2208
|
const selectedLeaf = textLeaves.find((leaf) => leaf.path.join(".") === selectedPath?.join(".")) ?? textLeaves[0];
|
|
2148
2209
|
const selectedElement = selectedPath ? getNodeAtPath(document2.children ?? [], selectedPath) : void 0;
|
|
2149
2210
|
const selectedCustomInspector = selectedElement && isElement(selectedElement) ? customInspectors?.[elementLabel(selectedElement)] ?? customInspectors?.[selectedElement.type] : void 0;
|
|
2150
|
-
const
|
|
2211
|
+
const validationOptions = useMemo(
|
|
2212
|
+
() => ({
|
|
2213
|
+
model: voiceModel ?? model,
|
|
2214
|
+
customVoiceDefinitions: voiceCatalog?.map((voice) => ({
|
|
2215
|
+
name: voice.name,
|
|
2216
|
+
locale: voice.locale,
|
|
2217
|
+
regions: voice.regions ?? (voice.region ? [voice.region] : void 0),
|
|
2218
|
+
styles: voice.styles,
|
|
2219
|
+
supportedTags: voice.supportedTags,
|
|
2220
|
+
unsupportedTags: voice.unsupportedTags,
|
|
2221
|
+
models: voice.models,
|
|
2222
|
+
status: voice.status ?? (voice.preview ? "preview" : "ga")
|
|
2223
|
+
}))
|
|
2224
|
+
}),
|
|
2225
|
+
[model, voiceCatalog, voiceModel]
|
|
2226
|
+
);
|
|
2227
|
+
const diagnostics = useMemo(
|
|
2228
|
+
() => validateAzureSsml(buildSsml(document2), validationOptions),
|
|
2229
|
+
[document2, validationOptions]
|
|
2230
|
+
);
|
|
2231
|
+
const getWarnings = (element) => elementWarnings(diagnostics, element);
|
|
2151
2232
|
const commit = (nextDocument) => onChange?.(nextDocument);
|
|
2152
2233
|
const applyWrapper = (tag, attributes) => {
|
|
2153
2234
|
if (readOnly || !selectedLeaf) return;
|
|
@@ -2162,7 +2243,8 @@ function VisualSsmlEditor({
|
|
|
2162
2243
|
node,
|
|
2163
2244
|
path: [index],
|
|
2164
2245
|
selectedPath,
|
|
2165
|
-
onSelect: setSelectedPath
|
|
2246
|
+
onSelect: setSelectedPath,
|
|
2247
|
+
getWarnings
|
|
2166
2248
|
}
|
|
2167
2249
|
)))), /* @__PURE__ */ React.createElement("div", { className: "ssml-editor-visual-form" }, selectedCustomInspector && selectedElement && isElement(selectedElement) ? selectedCustomInspector({
|
|
2168
2250
|
document: document2,
|
|
@@ -2179,9 +2261,10 @@ function VisualSsmlEditor({
|
|
|
2179
2261
|
onClick: () => commit(addDialogTurn(document2, selectedPath ?? []))
|
|
2180
2262
|
},
|
|
2181
2263
|
locale === "ja" ? "\u30BF\u30FC\u30F3\u3092\u8FFD\u52A0" : "Add turn"
|
|
2182
|
-
)) : selectedElement && isElement(selectedElement) && selectedElement.type === "mstts:turn" ? /* @__PURE__ */ React.createElement("fieldset", null, /* @__PURE__ */ React.createElement("legend", null, localizedElementLabel(selectedElement, locale)), /* @__PURE__ */ React.createElement("label", { htmlFor: "ssml-visual-turn-voice" }, locale === "ja" ? "\u97F3\u58F0" : "Voice", voiceCatalog ? (renderVoiceSelector ?? DefaultVoiceSelector)({
|
|
2264
|
+
)) : selectedElement && isElement(selectedElement) && selectedElement.type === "mstts:turn" ? /* @__PURE__ */ React.createElement("fieldset", null, /* @__PURE__ */ React.createElement("legend", null, localizedElementLabel(selectedElement, locale)), /* @__PURE__ */ React.createElement("label", { htmlFor: "ssml-visual-turn-voice" }, locale === "ja" ? "\u97F3\u58F0" : "Voice", /* @__PURE__ */ React.createElement(WarningBadge, { messages: elementWarnings(diagnostics, selectedElement) }), voiceCatalog ? (renderVoiceSelector ?? DefaultVoiceSelector)({
|
|
2183
2265
|
value: selectedElement.voice ?? "",
|
|
2184
2266
|
voices: filteredVoices(voiceCatalog, voiceLocale, voiceRegion, voiceStyle),
|
|
2267
|
+
selectedVoice: voiceCatalog?.find((voice) => voice.name === selectedElement.voice),
|
|
2185
2268
|
readOnly,
|
|
2186
2269
|
locale,
|
|
2187
2270
|
onChange: (value) => commit(updateOptionalElementProperty(document2, selectedPath ?? [], "voice", value))
|
|
@@ -2255,7 +2338,8 @@ function VisualSsmlEditor({
|
|
|
2255
2338
|
voiceCatalog,
|
|
2256
2339
|
voiceLocale,
|
|
2257
2340
|
voiceRegion,
|
|
2258
|
-
voiceStyle
|
|
2341
|
+
voiceStyle,
|
|
2342
|
+
diagnostics
|
|
2259
2343
|
}
|
|
2260
2344
|
) : selectedLeaf ? /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("label", null, "Text", /* @__PURE__ */ React.createElement(
|
|
2261
2345
|
"textarea",
|
|
@@ -2879,6 +2963,8 @@ var SsmlEditor = forwardRef(function SsmlEditor2({
|
|
|
2879
2963
|
voiceLocale,
|
|
2880
2964
|
voiceRegion,
|
|
2881
2965
|
voiceStyle,
|
|
2966
|
+
voiceModel,
|
|
2967
|
+
model,
|
|
2882
2968
|
emotionStyles,
|
|
2883
2969
|
className,
|
|
2884
2970
|
style,
|
|
@@ -3277,7 +3363,9 @@ var SsmlEditor = forwardRef(function SsmlEditor2({
|
|
|
3277
3363
|
voiceCatalog,
|
|
3278
3364
|
voiceLocale,
|
|
3279
3365
|
voiceRegion,
|
|
3280
|
-
voiceStyle
|
|
3366
|
+
voiceStyle,
|
|
3367
|
+
voiceModel,
|
|
3368
|
+
model
|
|
3281
3369
|
}
|
|
3282
3370
|
)) : /* @__PURE__ */ React.createElement("div", { style: { ...editorStyles.editor, minHeight: editorMinHeight } }, /* @__PURE__ */ React.createElement(
|
|
3283
3371
|
Editor,
|