ssml-builder-js 2.18.0 → 2.19.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/dist/react.mjs CHANGED
@@ -1980,22 +1980,35 @@ function voiceForPath(document2, path, voiceCatalog) {
1980
1980
  const voiceName = candidates.find((element) => element.type === "voice")?.name ?? candidates.find((element) => element.type === "mstts:turn")?.voice;
1981
1981
  return voiceName ? voiceCatalog.find((voice) => voice.name.toLowerCase() === voiceName.toLowerCase()) : void 0;
1982
1982
  }
1983
- function isVisualTagSupported(tagName, voice) {
1983
+ function normalizeVisualTagName(tagName) {
1984
+ const normalized = tagName.toLowerCase();
1985
+ if (normalized === "express-as" || normalized === "expressas" || normalized === "mstts:express-as")
1986
+ return "mstts:express-as";
1987
+ if (normalized === "sayas" || normalized === "say-as") return "say-as";
1988
+ return normalized;
1989
+ }
1990
+ function isVisualTagSupported(tagName, voice, model) {
1984
1991
  if (!voice) return true;
1985
- const tag = tagName.toLowerCase();
1986
- const unsupported = new Set((voice.unsupportedTags ?? []).map((candidate) => candidate.toLowerCase()));
1987
- const supported = voice.supportedTags?.map((candidate) => candidate.toLowerCase());
1992
+ const tag = normalizeVisualTagName(tagName);
1993
+ const unsupported = new Set((voice.unsupportedTags ?? []).map(normalizeVisualTagName));
1994
+ if (model && /neural[-_ ]?hd/i.test(model)) unsupported.add("emphasis");
1995
+ const supported = voice.supportedTags?.map(normalizeVisualTagName);
1988
1996
  return !unsupported.has(tag) && (supported === void 0 || supported.includes(tag));
1989
1997
  }
1990
1998
  function VoiceCapabilityMatrix({
1991
1999
  voice,
1992
- locale
2000
+ locale,
2001
+ model
1993
2002
  }) {
1994
2003
  const status = voice.status ?? (voice.preview ? "preview" : void 0);
1995
- 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(", ")));
2004
+ const unsupportedTags = [
2005
+ ...voice.unsupportedTags ?? [],
2006
+ ...model && /neural[-_ ]?hd/i.test(model) && !voice.unsupportedTags?.some((tag) => normalizeVisualTagName(tag) === "emphasis") ? ["emphasis"] : []
2007
+ ];
2008
+ 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(", ")), unsupportedTags.length > 0 && /* @__PURE__ */ React.createElement("div", { className: "ssml-editor-voice-unsupported" }, locale === "ja" ? "\u975E\u5BFE\u5FDC\u30BF\u30B0" : "Unsupported tags", ": ", unsupportedTags.join(", ")));
1996
2009
  }
1997
2010
  function diagnosticMatchesElement(diagnostic, element) {
1998
- const name = elementLabel(element).toLowerCase().replace("expressas", "mstts:express-as");
2011
+ const name = normalizeVisualTagName(elementLabel(element));
1999
2012
  if (diagnostic.code === "azure-unsupported-style") return name === "mstts:express-as" || name === "express-as";
2000
2013
  if (diagnostic.code === "azure-unsupported-tag-for-voice") {
2001
2014
  return diagnostic.message.toLowerCase().includes(`<${name}>`) || diagnostic.message.toLowerCase().includes(`<${name.replace("mstts:", "")}>`);
@@ -2062,9 +2075,10 @@ function VisualElementInspector({
2062
2075
  voiceRegion,
2063
2076
  voiceStyle,
2064
2077
  diagnostics,
2065
- voiceDefinition
2078
+ voiceDefinition,
2079
+ model
2066
2080
  }) {
2067
- const tagSupported = isVisualTagSupported(elementLabel(element), voiceDefinition);
2081
+ const tagSupported = isVisualTagSupported(elementLabel(element), voiceDefinition, model);
2068
2082
  if (customInspector) {
2069
2083
  return /* @__PURE__ */ React.createElement(React.Fragment, null, customInspector({ document: document2, element, path, readOnly: readOnly || !tagSupported, onChange: commit, locale }));
2070
2084
  }
@@ -2242,22 +2256,28 @@ function VisualSsmlEditor({
2242
2256
  const activeVoice = voiceForPath(document2, selectedPath ?? selectedLeaf?.path, voiceCatalog);
2243
2257
  const staleCatalog = voiceCatalogMetadata?.expiresAt ? Date.parse(voiceCatalogMetadata.expiresAt) <= Date.now() : false;
2244
2258
  const selectedCustomInspector = selectedElement && isElement(selectedElement) ? customInspectors?.[elementLabel(selectedElement)] ?? customInspectors?.[selectedElement.type] : void 0;
2245
- const validationOptions = useMemo(
2246
- () => ({
2247
- model: voiceModel ?? model,
2259
+ const validationOptions = useMemo(() => {
2260
+ const selectedModel = voiceModel ?? model;
2261
+ const hdUnsupportedTags = selectedModel && /neural[-_ ]?hd/i.test(selectedModel) ? ["emphasis"] : [];
2262
+ return {
2263
+ model: selectedModel,
2248
2264
  customVoiceDefinitions: voiceCatalog?.map((voice) => ({
2249
2265
  name: voice.name,
2250
2266
  locale: voice.locale,
2251
2267
  regions: voice.regions ?? (voice.region ? [voice.region] : void 0),
2252
2268
  styles: voice.styles,
2253
2269
  supportedTags: voice.supportedTags,
2254
- unsupportedTags: voice.unsupportedTags,
2270
+ unsupportedTags: [
2271
+ ...voice.unsupportedTags ?? [],
2272
+ ...hdUnsupportedTags.filter(
2273
+ (tag) => !voice.unsupportedTags?.some((candidate) => normalizeVisualTagName(candidate) === tag)
2274
+ )
2275
+ ],
2255
2276
  models: voice.models,
2256
2277
  status: voice.status ?? (voice.preview ? "preview" : "ga")
2257
2278
  }))
2258
- }),
2259
- [model, voiceCatalog, voiceModel]
2260
- );
2279
+ };
2280
+ }, [model, voiceCatalog, voiceModel]);
2261
2281
  const diagnostics = useMemo(
2262
2282
  () => validateAzureSsml(buildSsml(document2), validationOptions),
2263
2283
  [document2, validationOptions]
@@ -2284,14 +2304,14 @@ function VisualSsmlEditor({
2284
2304
  document: document2,
2285
2305
  element: selectedElement,
2286
2306
  path: selectedPath ?? [],
2287
- readOnly: readOnly || !isVisualTagSupported(elementLabel(selectedElement), activeVoice),
2307
+ readOnly: readOnly || !isVisualTagSupported(elementLabel(selectedElement), activeVoice, voiceModel ?? model),
2288
2308
  onChange: commit,
2289
2309
  locale
2290
2310
  }) : selectedElement && isElement(selectedElement) && selectedElement.type === "mstts:dialog" ? /* @__PURE__ */ React.createElement("fieldset", null, /* @__PURE__ */ React.createElement("legend", null, localizedElementLabel(selectedElement, locale)), /* @__PURE__ */ React.createElement("p", null, SSML_ELEMENT_COPY[locale][elementLabel(selectedElement)]?.description), /* @__PURE__ */ React.createElement(
2291
2311
  "button",
2292
2312
  {
2293
2313
  type: "button",
2294
- disabled: readOnly || !isVisualTagSupported("mstts:dialog", activeVoice),
2314
+ disabled: readOnly || !isVisualTagSupported("mstts:dialog", activeVoice, voiceModel ?? model),
2295
2315
  onClick: () => commit(addDialogTurn(document2, selectedPath ?? []))
2296
2316
  },
2297
2317
  locale === "ja" ? "\u30BF\u30FC\u30F3\u3092\u8FFD\u52A0" : "Add turn"
@@ -2374,7 +2394,8 @@ function VisualSsmlEditor({
2374
2394
  voiceRegion,
2375
2395
  voiceStyle,
2376
2396
  diagnostics,
2377
- voiceDefinition: activeVoice
2397
+ voiceDefinition: activeVoice,
2398
+ model: voiceModel ?? model
2378
2399
  }
2379
2400
  ) : selectedLeaf ? /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("label", null, "Text", /* @__PURE__ */ React.createElement(
2380
2401
  "textarea",
@@ -2388,7 +2409,7 @@ function VisualSsmlEditor({
2388
2409
  "button",
2389
2410
  {
2390
2411
  type: "button",
2391
- disabled: readOnly || !isVisualTagSupported("prosody", activeVoice),
2412
+ disabled: readOnly || !isVisualTagSupported("prosody", activeVoice, voiceModel ?? model),
2392
2413
  onClick: () => applyWrapper("prosody", { rate: "slow" })
2393
2414
  },
2394
2415
  "Rate"
@@ -2396,7 +2417,7 @@ function VisualSsmlEditor({
2396
2417
  "button",
2397
2418
  {
2398
2419
  type: "button",
2399
- disabled: readOnly || !isVisualTagSupported("prosody", activeVoice),
2420
+ disabled: readOnly || !isVisualTagSupported("prosody", activeVoice, voiceModel ?? model),
2400
2421
  onClick: () => applyWrapper("prosody", { pitch: "high" })
2401
2422
  },
2402
2423
  "Pitch"
@@ -2404,7 +2425,7 @@ function VisualSsmlEditor({
2404
2425
  "button",
2405
2426
  {
2406
2427
  type: "button",
2407
- disabled: readOnly || !isVisualTagSupported("mstts:express-as", activeVoice),
2428
+ disabled: readOnly || !isVisualTagSupported("mstts:express-as", activeVoice, voiceModel ?? model),
2408
2429
  onClick: () => applyWrapper("mstts:express-as", { style: "cheerful" })
2409
2430
  },
2410
2431
  "Emotion"
@@ -2412,7 +2433,7 @@ function VisualSsmlEditor({
2412
2433
  "button",
2413
2434
  {
2414
2435
  type: "button",
2415
- disabled: readOnly || !isVisualTagSupported("break", activeVoice),
2436
+ disabled: readOnly || !isVisualTagSupported("break", activeVoice, voiceModel ?? model),
2416
2437
  onClick: () => applyWrapper("break", { time: "500ms" })
2417
2438
  },
2418
2439
  "Pause"
@@ -2420,7 +2441,7 @@ function VisualSsmlEditor({
2420
2441
  "button",
2421
2442
  {
2422
2443
  type: "button",
2423
- disabled: readOnly || !isVisualTagSupported("phoneme", activeVoice),
2444
+ disabled: readOnly || !isVisualTagSupported("phoneme", activeVoice, voiceModel ?? model),
2424
2445
  onClick: () => applyWrapper("phoneme", { alphabet: "ipa", ph: selectedLeaf.value })
2425
2446
  },
2426
2447
  "Pronunciation"