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.js
CHANGED
|
@@ -2953,6 +2953,86 @@ var AZURE_VOICE_DEFINITIONS = [
|
|
|
2953
2953
|
},
|
|
2954
2954
|
{ name: "zh-TW-HsiaoChenNeural", locale: "zh-TW" }
|
|
2955
2955
|
];
|
|
2956
|
+
function createAzureUrlValidatorRunner(validator, options = {}) {
|
|
2957
|
+
if (typeof validator !== "function") throw new TypeError("A URL validator function is required.");
|
|
2958
|
+
const concurrency = options.concurrency === void 0 ? Infinity : Number.isFinite(options.concurrency) ? Math.max(1, Math.floor(options.concurrency)) : Infinity;
|
|
2959
|
+
const cache = options.cache ?? /* @__PURE__ */ new Map();
|
|
2960
|
+
const inFlight = /* @__PURE__ */ new Map();
|
|
2961
|
+
const waiters = [];
|
|
2962
|
+
let active = 0;
|
|
2963
|
+
const configuredSignal = options.signal ?? new AbortController().signal;
|
|
2964
|
+
const acquire = async (signal) => {
|
|
2965
|
+
if (signal.aborted) throw new Error("URL validation was aborted.");
|
|
2966
|
+
if (active < concurrency) {
|
|
2967
|
+
active += 1;
|
|
2968
|
+
return;
|
|
2969
|
+
}
|
|
2970
|
+
await new Promise((resolve, reject) => {
|
|
2971
|
+
let waiter;
|
|
2972
|
+
const abortHandler = () => {
|
|
2973
|
+
const index = waiters.indexOf(waiter);
|
|
2974
|
+
if (index >= 0) waiters.splice(index, 1);
|
|
2975
|
+
signal.removeEventListener("abort", abortHandler);
|
|
2976
|
+
reject(new Error("URL validation was aborted."));
|
|
2977
|
+
};
|
|
2978
|
+
signal.addEventListener("abort", abortHandler, { once: true });
|
|
2979
|
+
waiter = () => {
|
|
2980
|
+
signal.removeEventListener("abort", abortHandler);
|
|
2981
|
+
resolve();
|
|
2982
|
+
};
|
|
2983
|
+
waiters.push(waiter);
|
|
2984
|
+
});
|
|
2985
|
+
active += 1;
|
|
2986
|
+
};
|
|
2987
|
+
const release = () => {
|
|
2988
|
+
active -= 1;
|
|
2989
|
+
waiters.shift()?.();
|
|
2990
|
+
};
|
|
2991
|
+
const check = async (url, context, signal = configuredSignal) => {
|
|
2992
|
+
if (signal.aborted) throw new Error("URL validation was aborted.");
|
|
2993
|
+
const key = `${context.tag}:${context.attribute}:${url}`;
|
|
2994
|
+
const cached = cache.get(key);
|
|
2995
|
+
if (cached !== void 0) return cached;
|
|
2996
|
+
const existing = inFlight.get(key);
|
|
2997
|
+
if (existing) return existing;
|
|
2998
|
+
const promise = (async () => {
|
|
2999
|
+
await acquire(signal);
|
|
3000
|
+
try {
|
|
3001
|
+
if (signal.aborted) throw new Error("URL validation was aborted.");
|
|
3002
|
+
const validation = Promise.resolve(validator(url, context, signal));
|
|
3003
|
+
let timer;
|
|
3004
|
+
let abortHandler;
|
|
3005
|
+
const cancellation = new Promise((_resolve, reject) => {
|
|
3006
|
+
abortHandler = () => reject(new Error("URL validation was aborted."));
|
|
3007
|
+
signal.addEventListener("abort", abortHandler, { once: true });
|
|
3008
|
+
if (options.timeoutMs !== void 0 && options.timeoutMs > 0) {
|
|
3009
|
+
timer = setTimeout(
|
|
3010
|
+
() => reject(new Error(`URL validation timed out after ${options.timeoutMs} ms.`)),
|
|
3011
|
+
options.timeoutMs
|
|
3012
|
+
);
|
|
3013
|
+
}
|
|
3014
|
+
});
|
|
3015
|
+
try {
|
|
3016
|
+
const result = await (timer || abortHandler ? Promise.race([validation, cancellation]) : validation);
|
|
3017
|
+
cache.set(key, result);
|
|
3018
|
+
return result;
|
|
3019
|
+
} finally {
|
|
3020
|
+
if (timer) clearTimeout(timer);
|
|
3021
|
+
if (abortHandler) signal.removeEventListener("abort", abortHandler);
|
|
3022
|
+
}
|
|
3023
|
+
} finally {
|
|
3024
|
+
release();
|
|
3025
|
+
}
|
|
3026
|
+
})();
|
|
3027
|
+
inFlight.set(key, promise);
|
|
3028
|
+
try {
|
|
3029
|
+
return await promise;
|
|
3030
|
+
} finally {
|
|
3031
|
+
inFlight.delete(key);
|
|
3032
|
+
}
|
|
3033
|
+
};
|
|
3034
|
+
return (url, context, signal) => check(url, context, signal ?? configuredSignal);
|
|
3035
|
+
}
|
|
2956
3036
|
var ALLOWED_BREAK_STRENGTHS = /* @__PURE__ */ new Set(["none", "x-weak", "weak", "medium", "strong", "x-strong"]);
|
|
2957
3037
|
var ALLOWED_SAY_AS = /* @__PURE__ */ new Set([
|
|
2958
3038
|
"characters",
|
|
@@ -3237,23 +3317,23 @@ function validateVoiceFeatureMatrix(token, source, diagnostics, voiceName, defin
|
|
|
3237
3317
|
);
|
|
3238
3318
|
}
|
|
3239
3319
|
}
|
|
3240
|
-
function validateAudioSource(token, source, diagnostics, options,
|
|
3320
|
+
function validateAudioSource(token, source, diagnostics, options, elementName3) {
|
|
3241
3321
|
const src = attr(token, "src");
|
|
3242
3322
|
if (!src) {
|
|
3243
|
-
addDiagnostic(diagnostics, source, token.start, `<${
|
|
3323
|
+
addDiagnostic(diagnostics, source, token.start, `<${elementName3}> requires a "src" attribute.`);
|
|
3244
3324
|
return;
|
|
3245
3325
|
}
|
|
3246
3326
|
let parsed;
|
|
3247
3327
|
try {
|
|
3248
3328
|
parsed = new URL(src);
|
|
3249
3329
|
} catch {
|
|
3250
|
-
addDiagnostic(diagnostics, source, token.start, `<${
|
|
3330
|
+
addDiagnostic(diagnostics, source, token.start, `<${elementName3} src> must be an absolute HTTP(S) URL.`);
|
|
3251
3331
|
return;
|
|
3252
3332
|
}
|
|
3253
3333
|
if (parsed.username || parsed.password)
|
|
3254
|
-
addDiagnostic(diagnostics, source, token.start, `<${
|
|
3334
|
+
addDiagnostic(diagnostics, source, token.start, `<${elementName3} src> must not contain URL credentials.`);
|
|
3255
3335
|
if (parsed.protocol !== "https:" && !(options.allowHttpAudio && parsed.protocol === "http:"))
|
|
3256
|
-
addDiagnostic(diagnostics, source, token.start, `<${
|
|
3336
|
+
addDiagnostic(diagnostics, source, token.start, `<${elementName3} src> must use HTTPS.`);
|
|
3257
3337
|
const isAllowedOrigin = options.allowedAudioOrigins?.some((allowedOrigin) => {
|
|
3258
3338
|
try {
|
|
3259
3339
|
const configured = new URL(allowedOrigin);
|
|
@@ -3265,13 +3345,13 @@ function validateAudioSource(token, source, diagnostics, options, elementName2)
|
|
|
3265
3345
|
}
|
|
3266
3346
|
}) ?? false;
|
|
3267
3347
|
if (options.allowedAudioOrigins && !isAllowedOrigin)
|
|
3268
|
-
addDiagnostic(diagnostics, source, token.start, `<${
|
|
3348
|
+
addDiagnostic(diagnostics, source, token.start, `<${elementName3} src> origin "${parsed.origin}" is not allowed.`);
|
|
3269
3349
|
else if (!isAllowedOrigin && !options.allowExternalAudio)
|
|
3270
3350
|
addDiagnostic(
|
|
3271
3351
|
diagnostics,
|
|
3272
3352
|
source,
|
|
3273
3353
|
token.start,
|
|
3274
|
-
`<${
|
|
3354
|
+
`<${elementName3} src> external origin "${parsed.origin}" is blocked by default; set allowExternalAudio to true or provide allowedAudioOrigins.`
|
|
3275
3355
|
);
|
|
3276
3356
|
}
|
|
3277
3357
|
function validateElement(token, source, diagnostics, voiceName, options, voiceCatalog) {
|
|
@@ -3589,6 +3669,15 @@ function validateAzureSsml(ssml, options = {}) {
|
|
|
3589
3669
|
const diagnostics = validateAzureSsmlStatic(ssml, options);
|
|
3590
3670
|
const validator = options.urlValidator ?? options.customUrlValidator;
|
|
3591
3671
|
if (!validator || typeof ssml !== "string") return diagnostics;
|
|
3672
|
+
const runnerOptions = options.urlValidation ?? {};
|
|
3673
|
+
const boundedValidator = createAzureUrlValidatorRunner(validator, {
|
|
3674
|
+
...runnerOptions,
|
|
3675
|
+
...options.urlValidatorConcurrency !== void 0 ? { concurrency: options.urlValidatorConcurrency } : {},
|
|
3676
|
+
...options.urlValidatorTimeoutMs !== void 0 ? { timeoutMs: options.urlValidatorTimeoutMs } : {},
|
|
3677
|
+
...options.urlValidatorSignal ? { signal: options.urlValidatorSignal } : {},
|
|
3678
|
+
...options.urlValidatorCache ? { cache: options.urlValidatorCache } : {}
|
|
3679
|
+
});
|
|
3680
|
+
const validationSignal = options.urlValidatorSignal ?? options.urlValidation?.signal ?? new AbortController().signal;
|
|
3592
3681
|
let tokens;
|
|
3593
3682
|
try {
|
|
3594
3683
|
tokens = tokenizeElements(ssml);
|
|
@@ -3598,7 +3687,11 @@ function validateAzureSsml(ssml, options = {}) {
|
|
|
3598
3687
|
const checks = tokens.flatMap(
|
|
3599
3688
|
(token) => urlAttributes(token).map(async ({ attribute, value }) => {
|
|
3600
3689
|
try {
|
|
3601
|
-
const result = await
|
|
3690
|
+
const result = await boundedValidator(
|
|
3691
|
+
value,
|
|
3692
|
+
{ tag: token.name, attribute, ...options.sourceNodePath ? { sourceNodePath: options.sourceNodePath } : {} },
|
|
3693
|
+
validationSignal
|
|
3694
|
+
);
|
|
3602
3695
|
const valid = typeof result === "boolean" ? result : result.valid;
|
|
3603
3696
|
if (!valid) {
|
|
3604
3697
|
const reason = typeof result === "boolean" ? void 0 : result.reason;
|
|
@@ -6754,13 +6847,65 @@ function localizedElementLabel(element, locale) {
|
|
|
6754
6847
|
function filteredVoices(voiceCatalog, locale, region, style) {
|
|
6755
6848
|
return (voiceCatalog ?? []).filter((voice) => {
|
|
6756
6849
|
if (locale && voice.locale.toLowerCase() !== locale.toLowerCase()) return false;
|
|
6757
|
-
|
|
6850
|
+
const regions = [voice.region, ...voice.regions ?? []].filter(
|
|
6851
|
+
(candidate) => Boolean(candidate)
|
|
6852
|
+
);
|
|
6853
|
+
if (region && regions.length > 0 && !regions.some((candidate) => candidate.toLowerCase() === region.toLowerCase()))
|
|
6854
|
+
return false;
|
|
6758
6855
|
if (style && !voice.styles?.some((candidate) => candidate.toLowerCase() === style.toLowerCase())) return false;
|
|
6759
6856
|
return true;
|
|
6760
6857
|
});
|
|
6761
6858
|
}
|
|
6762
|
-
function
|
|
6859
|
+
function VoiceCapabilityMatrix({
|
|
6860
|
+
voice,
|
|
6861
|
+
locale
|
|
6862
|
+
}) {
|
|
6863
|
+
const status = voice.status ?? (voice.preview ? "preview" : void 0);
|
|
6864
|
+
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(", ")));
|
|
6865
|
+
}
|
|
6866
|
+
function diagnosticMatchesElement(diagnostic, element) {
|
|
6867
|
+
const name = elementLabel(element).toLowerCase().replace("expressas", "mstts:express-as");
|
|
6868
|
+
if (diagnostic.code === "azure-unsupported-style") return name === "mstts:express-as" || name === "express-as";
|
|
6869
|
+
if (diagnostic.code === "azure-unsupported-tag-for-voice") {
|
|
6870
|
+
return diagnostic.message.toLowerCase().includes(`<${name}>`) || diagnostic.message.toLowerCase().includes(`<${name.replace("mstts:", "")}>`);
|
|
6871
|
+
}
|
|
6872
|
+
if (diagnostic.code === "azure-locale-mismatch" || diagnostic.code === "azure-unsupported-model-for-voice")
|
|
6873
|
+
return name === "voice" || name === "mstts:turn";
|
|
6874
|
+
return false;
|
|
6875
|
+
}
|
|
6876
|
+
function elementWarnings(diagnostics, element) {
|
|
6877
|
+
return diagnostics.filter((diagnostic) => diagnosticMatchesElement(diagnostic, element));
|
|
6878
|
+
}
|
|
6879
|
+
function fieldWarnings(diagnostics, element, field) {
|
|
6880
|
+
return elementWarnings(diagnostics, element).filter((diagnostic) => {
|
|
6881
|
+
if (diagnostic.code === "azure-unsupported-style") return field.key === "style";
|
|
6882
|
+
return field.key === "name" || field.key === "voice";
|
|
6883
|
+
});
|
|
6884
|
+
}
|
|
6885
|
+
function WarningBadge({ messages }) {
|
|
6886
|
+
if (messages.length === 0) return null;
|
|
6763
6887
|
return /* @__PURE__ */ React.createElement(
|
|
6888
|
+
"span",
|
|
6889
|
+
{
|
|
6890
|
+
role: "status",
|
|
6891
|
+
"aria-label": messages.map((message) => message.message).join(" "),
|
|
6892
|
+
title: messages.map((message) => message.message).join(" "),
|
|
6893
|
+
"data-ssml-warning-badge": "",
|
|
6894
|
+
"data-testid": "ssml-editor-warning-badge",
|
|
6895
|
+
className: "ssml-editor-warning-badge"
|
|
6896
|
+
},
|
|
6897
|
+
"\u26A0"
|
|
6898
|
+
);
|
|
6899
|
+
}
|
|
6900
|
+
function DefaultVoiceSelector({
|
|
6901
|
+
value,
|
|
6902
|
+
voices,
|
|
6903
|
+
selectedVoice,
|
|
6904
|
+
readOnly,
|
|
6905
|
+
locale,
|
|
6906
|
+
onChange
|
|
6907
|
+
}) {
|
|
6908
|
+
return /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement(
|
|
6764
6909
|
"select",
|
|
6765
6910
|
{
|
|
6766
6911
|
"aria-label": locale === "ja" ? "\u97F3\u58F0" : "Voice",
|
|
@@ -6770,7 +6915,7 @@ function DefaultVoiceSelector({ value, voices, readOnly, locale, onChange }) {
|
|
|
6770
6915
|
},
|
|
6771
6916
|
/* @__PURE__ */ React.createElement("option", { value: "" }, locale === "ja" ? "\u97F3\u58F0\u3092\u9078\u629E" : "Select a voice"),
|
|
6772
6917
|
voices.map((voice) => /* @__PURE__ */ React.createElement("option", { key: voice.name, value: voice.name }, voice.name, voice.preview || voice.status === "preview" ? " (preview)" : ""))
|
|
6773
|
-
);
|
|
6918
|
+
), selectedVoice ? /* @__PURE__ */ React.createElement(VoiceCapabilityMatrix, { voice: selectedVoice, locale }) : null);
|
|
6774
6919
|
}
|
|
6775
6920
|
function VisualElementInspector({
|
|
6776
6921
|
document: document2,
|
|
@@ -6784,15 +6929,19 @@ function VisualElementInspector({
|
|
|
6784
6929
|
voiceCatalog,
|
|
6785
6930
|
voiceLocale,
|
|
6786
6931
|
voiceRegion,
|
|
6787
|
-
voiceStyle
|
|
6932
|
+
voiceStyle,
|
|
6933
|
+
diagnostics
|
|
6788
6934
|
}) {
|
|
6789
6935
|
if (customInspector) {
|
|
6790
6936
|
return /* @__PURE__ */ React.createElement(React.Fragment, null, customInspector({ document: document2, element, path, readOnly, onChange: commit, locale }));
|
|
6791
6937
|
}
|
|
6792
6938
|
const fields = getElementFields(element);
|
|
6793
6939
|
const availableVoices = filteredVoices(voiceCatalog, voiceLocale, voiceRegion, voiceStyle);
|
|
6940
|
+
const selectedVoice = voiceCatalog?.find(
|
|
6941
|
+
(voice) => voice.name === (element.type === "voice" ? element.name : void 0)
|
|
6942
|
+
);
|
|
6794
6943
|
const renderSelector = renderVoiceSelector ?? DefaultVoiceSelector;
|
|
6795
|
-
return /* @__PURE__ */ React.createElement("fieldset", null, /* @__PURE__ */ React.createElement("legend", null, `<${elementLabel(element)}
|
|
6944
|
+
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) => {
|
|
6796
6945
|
const value = element[field.key];
|
|
6797
6946
|
const inputValue = value === void 0 ? "" : String(value);
|
|
6798
6947
|
const inputId = `ssml-visual-${field.key}`;
|
|
@@ -6829,9 +6978,10 @@ function VisualElementInspector({
|
|
|
6829
6978
|
speakerProfileId: "\u8A71\u8005\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB ID",
|
|
6830
6979
|
url: "\u97F3\u58F0\u5909\u63DB URL",
|
|
6831
6980
|
profile: "\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB"
|
|
6832
|
-
}[field.key] ?? field.label : field.label, field.key === "name" && elementLabel(element) === "voice" && voiceCatalog ? renderSelector({
|
|
6981
|
+
}[field.key] ?? field.label : field.label, /* @__PURE__ */ React.createElement(WarningBadge, { messages: fieldWarnings(diagnostics, element, field) }), field.key === "name" && elementLabel(element) === "voice" && voiceCatalog ? renderSelector({
|
|
6833
6982
|
value: inputValue,
|
|
6834
6983
|
voices: availableVoices,
|
|
6984
|
+
selectedVoice,
|
|
6835
6985
|
readOnly,
|
|
6836
6986
|
locale,
|
|
6837
6987
|
onChange: (value2) => commit(updateOptionalElementProperty(document2, path, field.key, value2))
|
|
@@ -6906,19 +7056,21 @@ function TreeNode({
|
|
|
6906
7056
|
node,
|
|
6907
7057
|
path,
|
|
6908
7058
|
selectedPath,
|
|
6909
|
-
onSelect
|
|
7059
|
+
onSelect,
|
|
7060
|
+
getWarnings
|
|
6910
7061
|
}) {
|
|
6911
7062
|
if (!isElement(node)) return null;
|
|
6912
7063
|
const name = elementLabel(node);
|
|
6913
7064
|
const isSelected = selectedPath?.join(".") === path.join(".");
|
|
6914
|
-
return /* @__PURE__ */ React.createElement("li", null, /* @__PURE__ */ React.createElement("button", { type: "button", "aria-current": isSelected ? "true" : void 0, onClick: () => onSelect(path) }, `<${name}
|
|
7065
|
+
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(
|
|
6915
7066
|
TreeNode,
|
|
6916
7067
|
{
|
|
6917
7068
|
key: `${path.join(".")}/${isElement(child) ? elementLabel(child) : JSON.stringify(child)}`,
|
|
6918
7069
|
node: child,
|
|
6919
7070
|
path: [...path, index],
|
|
6920
7071
|
selectedPath,
|
|
6921
|
-
onSelect
|
|
7072
|
+
onSelect,
|
|
7073
|
+
getWarnings
|
|
6922
7074
|
}
|
|
6923
7075
|
))));
|
|
6924
7076
|
}
|
|
@@ -6933,7 +7085,9 @@ function VisualSsmlEditor({
|
|
|
6933
7085
|
voiceCatalog,
|
|
6934
7086
|
voiceLocale,
|
|
6935
7087
|
voiceRegion,
|
|
6936
|
-
voiceStyle
|
|
7088
|
+
voiceStyle,
|
|
7089
|
+
voiceModel,
|
|
7090
|
+
model
|
|
6937
7091
|
}) {
|
|
6938
7092
|
const [selectedPath, setSelectedPath] = (0, import_react3.useState)(null);
|
|
6939
7093
|
const [selection, setSelection] = (0, import_react3.useState)({ start: 0, end: 0 });
|
|
@@ -6941,7 +7095,27 @@ function VisualSsmlEditor({
|
|
|
6941
7095
|
const selectedLeaf = textLeaves.find((leaf) => leaf.path.join(".") === selectedPath?.join(".")) ?? textLeaves[0];
|
|
6942
7096
|
const selectedElement = selectedPath ? getNodeAtPath(document2.children ?? [], selectedPath) : void 0;
|
|
6943
7097
|
const selectedCustomInspector = selectedElement && isElement(selectedElement) ? customInspectors?.[elementLabel(selectedElement)] ?? customInspectors?.[selectedElement.type] : void 0;
|
|
6944
|
-
const
|
|
7098
|
+
const validationOptions = (0, import_react3.useMemo)(
|
|
7099
|
+
() => ({
|
|
7100
|
+
model: voiceModel ?? model,
|
|
7101
|
+
customVoiceDefinitions: voiceCatalog?.map((voice) => ({
|
|
7102
|
+
name: voice.name,
|
|
7103
|
+
locale: voice.locale,
|
|
7104
|
+
regions: voice.regions ?? (voice.region ? [voice.region] : void 0),
|
|
7105
|
+
styles: voice.styles,
|
|
7106
|
+
supportedTags: voice.supportedTags,
|
|
7107
|
+
unsupportedTags: voice.unsupportedTags,
|
|
7108
|
+
models: voice.models,
|
|
7109
|
+
status: voice.status ?? (voice.preview ? "preview" : "ga")
|
|
7110
|
+
}))
|
|
7111
|
+
}),
|
|
7112
|
+
[model, voiceCatalog, voiceModel]
|
|
7113
|
+
);
|
|
7114
|
+
const diagnostics = (0, import_react3.useMemo)(
|
|
7115
|
+
() => validateAzureSsml(buildSsml(document2), validationOptions),
|
|
7116
|
+
[document2, validationOptions]
|
|
7117
|
+
);
|
|
7118
|
+
const getWarnings = (element) => elementWarnings(diagnostics, element);
|
|
6945
7119
|
const commit = (nextDocument) => onChange?.(nextDocument);
|
|
6946
7120
|
const applyWrapper = (tag, attributes) => {
|
|
6947
7121
|
if (readOnly || !selectedLeaf) return;
|
|
@@ -6956,7 +7130,8 @@ function VisualSsmlEditor({
|
|
|
6956
7130
|
node,
|
|
6957
7131
|
path: [index],
|
|
6958
7132
|
selectedPath,
|
|
6959
|
-
onSelect: setSelectedPath
|
|
7133
|
+
onSelect: setSelectedPath,
|
|
7134
|
+
getWarnings
|
|
6960
7135
|
}
|
|
6961
7136
|
)))), /* @__PURE__ */ React.createElement("div", { className: "ssml-editor-visual-form" }, selectedCustomInspector && selectedElement && isElement(selectedElement) ? selectedCustomInspector({
|
|
6962
7137
|
document: document2,
|
|
@@ -6973,9 +7148,10 @@ function VisualSsmlEditor({
|
|
|
6973
7148
|
onClick: () => commit(addDialogTurn(document2, selectedPath ?? []))
|
|
6974
7149
|
},
|
|
6975
7150
|
locale === "ja" ? "\u30BF\u30FC\u30F3\u3092\u8FFD\u52A0" : "Add turn"
|
|
6976
|
-
)) : 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)({
|
|
7151
|
+
)) : 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)({
|
|
6977
7152
|
value: selectedElement.voice ?? "",
|
|
6978
7153
|
voices: filteredVoices(voiceCatalog, voiceLocale, voiceRegion, voiceStyle),
|
|
7154
|
+
selectedVoice: voiceCatalog?.find((voice) => voice.name === selectedElement.voice),
|
|
6979
7155
|
readOnly,
|
|
6980
7156
|
locale,
|
|
6981
7157
|
onChange: (value) => commit(updateOptionalElementProperty(document2, selectedPath ?? [], "voice", value))
|
|
@@ -7049,7 +7225,8 @@ function VisualSsmlEditor({
|
|
|
7049
7225
|
voiceCatalog,
|
|
7050
7226
|
voiceLocale,
|
|
7051
7227
|
voiceRegion,
|
|
7052
|
-
voiceStyle
|
|
7228
|
+
voiceStyle,
|
|
7229
|
+
diagnostics
|
|
7053
7230
|
}
|
|
7054
7231
|
) : selectedLeaf ? /* @__PURE__ */ React.createElement(React.Fragment, null, /* @__PURE__ */ React.createElement("label", null, "Text", /* @__PURE__ */ React.createElement(
|
|
7055
7232
|
"textarea",
|
|
@@ -7673,6 +7850,8 @@ var SsmlEditor = (0, import_react4.forwardRef)(function SsmlEditor2({
|
|
|
7673
7850
|
voiceLocale,
|
|
7674
7851
|
voiceRegion,
|
|
7675
7852
|
voiceStyle,
|
|
7853
|
+
voiceModel,
|
|
7854
|
+
model,
|
|
7676
7855
|
emotionStyles,
|
|
7677
7856
|
className,
|
|
7678
7857
|
style,
|
|
@@ -8071,7 +8250,9 @@ var SsmlEditor = (0, import_react4.forwardRef)(function SsmlEditor2({
|
|
|
8071
8250
|
voiceCatalog,
|
|
8072
8251
|
voiceLocale,
|
|
8073
8252
|
voiceRegion,
|
|
8074
|
-
voiceStyle
|
|
8253
|
+
voiceStyle,
|
|
8254
|
+
voiceModel,
|
|
8255
|
+
model
|
|
8075
8256
|
}
|
|
8076
8257
|
)) : /* @__PURE__ */ React.createElement("div", { style: { ...editorStyles.editor, minHeight: editorMinHeight } }, /* @__PURE__ */ React.createElement(
|
|
8077
8258
|
import_react5.default,
|