ssml-builder-js 2.11.0 → 2.12.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/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-SNRI43QJ.mjs";
18
+ } from "./chunk-4BVNAUVR.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
- return new URL(allowedOrigin).origin === parsed.origin;
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 allowedOrigin === parsed.origin;
1328
+ return false;
1323
1329
  }
1324
1330
  }) ?? false;
1325
1331
  if (options.allowedAudioOrigins && !isAllowedOrigin)
@@ -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");