ssml-builder-js 2.11.0 → 2.13.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 +61 -3
- package/dist/{chunk-SNRI43QJ.mjs → chunk-25LOR4AJ.mjs} +248 -4
- package/dist/chunk-25LOR4AJ.mjs.map +1 -0
- package/dist/chunk-CZ2F3TET.mjs +1745 -0
- package/dist/chunk-CZ2F3TET.mjs.map +1 -0
- package/dist/{chunk-FWWMWI2C.mjs → chunk-LCTE26LS.mjs} +248 -1701
- package/dist/chunk-LCTE26LS.mjs.map +1 -0
- package/dist/core.d.mts +54 -2
- package/dist/core.d.ts +54 -2
- package/dist/core.js +248 -3
- package/dist/core.js.map +1 -1
- package/dist/core.mjs +3 -1
- package/dist/elements.js +141 -3
- package/dist/elements.js.map +1 -1
- package/dist/elements.mjs +6 -4
- package/dist/elements.mjs.map +1 -1
- package/dist/index.d-Xbr6ZWnK.d.mts +214 -0
- package/dist/index.d-Xbr6ZWnK.d.ts +214 -0
- package/dist/index.d.mts +123 -2
- package/dist/index.d.ts +123 -2
- package/dist/index.js +1882 -18
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +176 -3
- package/dist/index.mjs.map +1 -1
- package/dist/react.d.mts +61 -163
- package/dist/react.d.ts +61 -163
- package/dist/react.js +557 -16
- package/dist/react.js.map +1 -1
- package/dist/react.mjs +276 -17
- package/dist/react.mjs.map +1 -1
- package/package.json +3 -2
- package/dist/chunk-FWWMWI2C.mjs.map +0 -1
- package/dist/chunk-SNRI43QJ.mjs.map +0 -1
package/dist/core.mjs
CHANGED
|
@@ -11,10 +11,11 @@ import {
|
|
|
11
11
|
mapSsmlTextNodes,
|
|
12
12
|
normalizeAzureLanguage,
|
|
13
13
|
parseSsml,
|
|
14
|
+
splitSsmlDocument,
|
|
14
15
|
validateAzureSsml,
|
|
15
16
|
validateSsml,
|
|
16
17
|
validateSsmlStructureIntegrity
|
|
17
|
-
} from "./chunk-
|
|
18
|
+
} from "./chunk-25LOR4AJ.mjs";
|
|
18
19
|
import "./chunk-6S5ODO6A.mjs";
|
|
19
20
|
export {
|
|
20
21
|
areAzureLanguagesEquivalent,
|
|
@@ -29,6 +30,7 @@ export {
|
|
|
29
30
|
mapSsmlTextNodes,
|
|
30
31
|
normalizeAzureLanguage,
|
|
31
32
|
parseSsml,
|
|
33
|
+
splitSsmlDocument,
|
|
32
34
|
validateAzureSsml,
|
|
33
35
|
validateSsml,
|
|
34
36
|
validateSsmlStructureIntegrity
|
package/dist/elements.js
CHANGED
|
@@ -1133,6 +1133,7 @@ function tokenizeElements(source) {
|
|
|
1133
1133
|
attributes,
|
|
1134
1134
|
childElementIndex,
|
|
1135
1135
|
end,
|
|
1136
|
+
depth: openElements.length + 1,
|
|
1136
1137
|
name: tokenName,
|
|
1137
1138
|
parentName: parent?.name,
|
|
1138
1139
|
parentVoiceName,
|
|
@@ -1313,13 +1314,18 @@ function validateAudioSource(token, source, diagnostics, options, elementName2)
|
|
|
1313
1314
|
addDiagnostic(diagnostics, source, token.start, `<${elementName2} src> must be an absolute HTTP(S) URL.`);
|
|
1314
1315
|
return;
|
|
1315
1316
|
}
|
|
1317
|
+
if (parsed.username || parsed.password)
|
|
1318
|
+
addDiagnostic(diagnostics, source, token.start, `<${elementName2} src> must not contain URL credentials.`);
|
|
1316
1319
|
if (parsed.protocol !== "https:" && !(options.allowHttpAudio && parsed.protocol === "http:"))
|
|
1317
1320
|
addDiagnostic(diagnostics, source, token.start, `<${elementName2} src> must use HTTPS.`);
|
|
1318
1321
|
const isAllowedOrigin = options.allowedAudioOrigins?.some((allowedOrigin) => {
|
|
1319
1322
|
try {
|
|
1320
|
-
|
|
1323
|
+
const configured = new URL(allowedOrigin);
|
|
1324
|
+
if (configured.protocol !== "https:" && configured.protocol !== "http:" || configured.username || configured.password || configured.pathname !== "/" || configured.search || configured.hash)
|
|
1325
|
+
return false;
|
|
1326
|
+
return configured.origin === parsed.origin;
|
|
1321
1327
|
} catch {
|
|
1322
|
-
return
|
|
1328
|
+
return false;
|
|
1323
1329
|
}
|
|
1324
1330
|
}) ?? false;
|
|
1325
1331
|
if (options.allowedAudioOrigins && !isAllowedOrigin)
|
|
@@ -1511,7 +1517,7 @@ function validateElement(token, source, diagnostics, voiceName, options, voiceCa
|
|
|
1511
1517
|
addDiagnostic(diagnostics, source, token.start, "<mstts:backgroundaudio> must be self-closing.");
|
|
1512
1518
|
}
|
|
1513
1519
|
}
|
|
1514
|
-
function
|
|
1520
|
+
function validateAzureSsmlStatic(ssml, options = {}) {
|
|
1515
1521
|
const diagnostics = [];
|
|
1516
1522
|
if (typeof ssml !== "string") {
|
|
1517
1523
|
return [
|
|
@@ -1527,6 +1533,9 @@ function validateAzureSsml(ssml, options = {}) {
|
|
|
1527
1533
|
const maxLength = options.maxLength ?? 1e4;
|
|
1528
1534
|
if (ssml.length > maxLength)
|
|
1529
1535
|
addDiagnostic(diagnostics, ssml, maxLength, `SSML exceeds the maximum length of ${maxLength} characters.`);
|
|
1536
|
+
if (options.maxXmlDepth !== void 0 && (!Number.isInteger(options.maxXmlDepth) || options.maxXmlDepth <= 0)) {
|
|
1537
|
+
addDiagnostic(diagnostics, ssml, 0, "maxXmlDepth must be a positive integer.");
|
|
1538
|
+
}
|
|
1530
1539
|
try {
|
|
1531
1540
|
parseSsml(ssml);
|
|
1532
1541
|
} catch (error) {
|
|
@@ -1536,6 +1545,18 @@ function validateAzureSsml(ssml, options = {}) {
|
|
|
1536
1545
|
return diagnostics;
|
|
1537
1546
|
}
|
|
1538
1547
|
const tokens = tokenizeElements(ssml);
|
|
1548
|
+
if (options.maxXmlDepth !== void 0) {
|
|
1549
|
+
for (const token of tokens) {
|
|
1550
|
+
if (token.depth > options.maxXmlDepth) {
|
|
1551
|
+
addDiagnostic(
|
|
1552
|
+
diagnostics,
|
|
1553
|
+
ssml,
|
|
1554
|
+
token.start,
|
|
1555
|
+
`XML nesting depth ${token.depth} exceeds the configured maximum of ${options.maxXmlDepth}.`
|
|
1556
|
+
);
|
|
1557
|
+
}
|
|
1558
|
+
}
|
|
1559
|
+
}
|
|
1539
1560
|
const speak = tokens.find((token) => token.name.toLowerCase() === "speak");
|
|
1540
1561
|
const voices = tokens.filter((token) => token.name.toLowerCase() === "voice");
|
|
1541
1562
|
const backgroundAudioTokens = tokens.filter((token) => token.name.toLowerCase() === "mstts:backgroundaudio");
|
|
@@ -1620,6 +1641,51 @@ function validateAzureSsml(ssml, options = {}) {
|
|
|
1620
1641
|
}
|
|
1621
1642
|
return diagnostics;
|
|
1622
1643
|
}
|
|
1644
|
+
function urlAttributes(token) {
|
|
1645
|
+
const tag = canonicalTagName(token.name);
|
|
1646
|
+
const attributes = tag === "audio" || tag === "mstts:backgroundaudio" ? ["src"] : tag === "lexicon" ? ["uri"] : tag === "mstts:voiceconversion" ? ["url"] : [];
|
|
1647
|
+
return attributes.flatMap((attribute) => {
|
|
1648
|
+
const value = attr(token, attribute);
|
|
1649
|
+
return value === void 0 ? [] : [{ attribute, value }];
|
|
1650
|
+
});
|
|
1651
|
+
}
|
|
1652
|
+
function validateAzureSsml(ssml, options = {}) {
|
|
1653
|
+
const diagnostics = validateAzureSsmlStatic(ssml, options);
|
|
1654
|
+
const validator = options.urlValidator ?? options.customUrlValidator;
|
|
1655
|
+
if (!validator || typeof ssml !== "string") return diagnostics;
|
|
1656
|
+
let tokens;
|
|
1657
|
+
try {
|
|
1658
|
+
tokens = tokenizeElements(ssml);
|
|
1659
|
+
} catch {
|
|
1660
|
+
return diagnostics;
|
|
1661
|
+
}
|
|
1662
|
+
const checks = tokens.flatMap(
|
|
1663
|
+
(token) => urlAttributes(token).map(async ({ attribute, value }) => {
|
|
1664
|
+
try {
|
|
1665
|
+
const result = await validator(value, { tag: token.name, attribute });
|
|
1666
|
+
const valid = typeof result === "boolean" ? result : result.valid;
|
|
1667
|
+
if (!valid) {
|
|
1668
|
+
const reason = typeof result === "boolean" ? void 0 : result.reason;
|
|
1669
|
+
addDiagnostic(
|
|
1670
|
+
diagnostics,
|
|
1671
|
+
ssml,
|
|
1672
|
+
token.start,
|
|
1673
|
+
`<${token.name} ${attribute}> was rejected by the custom URL validator${reason ? `: ${reason}` : "."}`
|
|
1674
|
+
);
|
|
1675
|
+
}
|
|
1676
|
+
} catch (error) {
|
|
1677
|
+
const reason = error instanceof Error ? error.message : String(error);
|
|
1678
|
+
addDiagnostic(
|
|
1679
|
+
diagnostics,
|
|
1680
|
+
ssml,
|
|
1681
|
+
token.start,
|
|
1682
|
+
`<${token.name} ${attribute}> could not be validated by the custom URL validator: ${reason}`
|
|
1683
|
+
);
|
|
1684
|
+
}
|
|
1685
|
+
})
|
|
1686
|
+
);
|
|
1687
|
+
return Promise.all(checks).then(() => diagnostics);
|
|
1688
|
+
}
|
|
1623
1689
|
var AZURE_VOICE_CATALOG_METADATA = {
|
|
1624
1690
|
apiVersion: "2025-10-01",
|
|
1625
1691
|
generatedAt: "2026-08-28T00:00:00.000Z",
|
|
@@ -3557,6 +3623,42 @@ var SSML_HOVER_COPY = {
|
|
|
3557
3623
|
parameters: {
|
|
3558
3624
|
value: { title: "value", description: "\u76EE\u6A19\u6642\u9593\u3002\u4F8B: `10s`\u3001`5000ms`\u3001`00:00:10`\u3002" }
|
|
3559
3625
|
}
|
|
3626
|
+
},
|
|
3627
|
+
"mstts:dialog": { title: "\u30C0\u30A4\u30A2\u30ED\u30B0", description: "\u8907\u6570\u306E\u8A71\u8005\u30BF\u30FC\u30F3\u3092\u307E\u3068\u3081\u307E\u3059\u3002", parameters: {} },
|
|
3628
|
+
"mstts:turn": {
|
|
3629
|
+
title: "\u8A71\u8005\u30BF\u30FC\u30F3",
|
|
3630
|
+
description: "\u30C0\u30A4\u30A2\u30ED\u30B0\u5185\u306E\u8A71\u8005\u3068\u767A\u8A71\u5185\u5BB9\u3092\u6307\u5B9A\u3057\u307E\u3059\u3002",
|
|
3631
|
+
parameters: {
|
|
3632
|
+
voice: { title: "voice", description: "\u3053\u306E\u30BF\u30FC\u30F3\u3067\u4F7F\u7528\u3059\u308B Azure \u97F3\u58F0\u540D\u3002" },
|
|
3633
|
+
speaker: { title: "speaker", description: "\u8A71\u8005\u8B58\u5225\u5B50\u3002" }
|
|
3634
|
+
}
|
|
3635
|
+
},
|
|
3636
|
+
"mstts:backgroundaudio": {
|
|
3637
|
+
title: "\u80CC\u666F\u97F3\u58F0",
|
|
3638
|
+
description: "\u5408\u6210\u97F3\u58F0\u306E\u80CC\u5F8C\u3067\u518D\u751F\u3059\u308B\u97F3\u58F0\u30D5\u30A1\u30A4\u30EB\u3092\u6307\u5B9A\u3057\u307E\u3059\u3002",
|
|
3639
|
+
parameters: { src: { title: "src", description: "\u97F3\u58F0\u30D5\u30A1\u30A4\u30EB\u306E HTTPS URL\u3002" } }
|
|
3640
|
+
},
|
|
3641
|
+
"mstts:ttsembedding": {
|
|
3642
|
+
title: "\u97F3\u58F0\u57CB\u3081\u8FBC\u307F",
|
|
3643
|
+
description: "\u30AB\u30B9\u30BF\u30E0\u97F3\u58F0\u307E\u305F\u306F\u8A71\u8005\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB\u306E\u30E1\u30BF\u30C7\u30FC\u30BF\u3092\u57CB\u3081\u8FBC\u307F\u307E\u3059\u3002",
|
|
3644
|
+
parameters: { speakerProfileId: { title: "speakerProfileId", description: "\u8A71\u8005\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB ID\u3002" } }
|
|
3645
|
+
},
|
|
3646
|
+
"mstts:embedding": {
|
|
3647
|
+
title: "\u57CB\u3081\u8FBC\u307F",
|
|
3648
|
+
description: "\u8A71\u8005\u57CB\u3081\u8FBC\u307F\u306E\u30E1\u30BF\u30C7\u30FC\u30BF\u3092\u6307\u5B9A\u3057\u307E\u3059\u3002",
|
|
3649
|
+
parameters: {
|
|
3650
|
+
id: { title: "id", description: "\u57CB\u3081\u8FBC\u307F ID\u3002" },
|
|
3651
|
+
speakerProfileId: { title: "speakerProfileId", description: "\u8A71\u8005\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB ID\u3002" }
|
|
3652
|
+
}
|
|
3653
|
+
},
|
|
3654
|
+
"mstts:voiceconversion": {
|
|
3655
|
+
title: "\u97F3\u58F0\u5909\u63DB",
|
|
3656
|
+
description: "\u30AB\u30B9\u30BF\u30E0\u97F3\u58F0\u306E\u5909\u63DB\u30E1\u30BF\u30C7\u30FC\u30BF\u3092\u6307\u5B9A\u3057\u307E\u3059\u3002",
|
|
3657
|
+
parameters: {
|
|
3658
|
+
url: { title: "url", description: "\u97F3\u58F0\u5909\u63DB\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB URL\u3002" },
|
|
3659
|
+
profile: { title: "profile", description: "\u5909\u63DB\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB\u3002" },
|
|
3660
|
+
speakerProfileId: { title: "speakerProfileId", description: "\u8A71\u8005\u30D7\u30ED\u30D5\u30A1\u30A4\u30EB ID\u3002" }
|
|
3661
|
+
}
|
|
3560
3662
|
}
|
|
3561
3663
|
}
|
|
3562
3664
|
},
|
|
@@ -3721,6 +3823,42 @@ var SSML_HOVER_COPY = {
|
|
|
3721
3823
|
parameters: {
|
|
3722
3824
|
value: { title: "value", description: "The target duration, such as `10s`, `5000ms`, or `00:00:10`." }
|
|
3723
3825
|
}
|
|
3826
|
+
},
|
|
3827
|
+
"mstts:dialog": { title: "Dialog", description: "Groups multiple speaker turns.", parameters: {} },
|
|
3828
|
+
"mstts:turn": {
|
|
3829
|
+
title: "Dialog turn",
|
|
3830
|
+
description: "Specifies a speaker and utterance within a dialog.",
|
|
3831
|
+
parameters: {
|
|
3832
|
+
voice: { title: "voice", description: "The Azure voice used by this turn." },
|
|
3833
|
+
speaker: { title: "speaker", description: "The speaker identifier." }
|
|
3834
|
+
}
|
|
3835
|
+
},
|
|
3836
|
+
"mstts:backgroundaudio": {
|
|
3837
|
+
title: "Background audio",
|
|
3838
|
+
description: "Specifies an audio file played behind synthesized speech.",
|
|
3839
|
+
parameters: { src: { title: "src", description: "The HTTPS URL of the audio file." } }
|
|
3840
|
+
},
|
|
3841
|
+
"mstts:ttsembedding": {
|
|
3842
|
+
title: "TTS embedding",
|
|
3843
|
+
description: "Embeds custom voice or speaker profile metadata.",
|
|
3844
|
+
parameters: { speakerProfileId: { title: "speakerProfileId", description: "The speaker profile ID." } }
|
|
3845
|
+
},
|
|
3846
|
+
"mstts:embedding": {
|
|
3847
|
+
title: "Embedding",
|
|
3848
|
+
description: "Specifies speaker embedding metadata.",
|
|
3849
|
+
parameters: {
|
|
3850
|
+
id: { title: "id", description: "The embedding ID." },
|
|
3851
|
+
speakerProfileId: { title: "speakerProfileId", description: "The speaker profile ID." }
|
|
3852
|
+
}
|
|
3853
|
+
},
|
|
3854
|
+
"mstts:voiceconversion": {
|
|
3855
|
+
title: "Voice conversion",
|
|
3856
|
+
description: "Specifies custom voice conversion metadata.",
|
|
3857
|
+
parameters: {
|
|
3858
|
+
url: { title: "url", description: "The voice conversion profile URL." },
|
|
3859
|
+
profile: { title: "profile", description: "The conversion profile." },
|
|
3860
|
+
speakerProfileId: { title: "speakerProfileId", description: "The speaker profile ID." }
|
|
3861
|
+
}
|
|
3724
3862
|
}
|
|
3725
3863
|
}
|
|
3726
3864
|
}
|