ssml-builder-js 2.15.0 → 2.16.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
@@ -15,9 +15,10 @@ import {
15
15
  parseSsml,
16
16
  splitSsmlDocument,
17
17
  validateAzureSsml,
18
+ validateAzureSsmlChunks,
18
19
  validateSsml,
19
20
  validateSsmlStructureIntegrity
20
- } from "./chunk-FXUM45ZY.mjs";
21
+ } from "./chunk-NKLZGITR.mjs";
21
22
  import "./chunk-6S5ODO6A.mjs";
22
23
  export {
23
24
  areAzureLanguagesEquivalent,
@@ -36,6 +37,7 @@ export {
36
37
  parseSsml,
37
38
  splitSsmlDocument,
38
39
  validateAzureSsml,
40
+ validateAzureSsmlChunks,
39
41
  validateSsml,
40
42
  validateSsmlStructureIntegrity
41
43
  };
package/dist/elements.js CHANGED
@@ -1208,6 +1208,7 @@ function tokenizeElements(source) {
1208
1208
  if (parent) parent.childElementCount += 1;
1209
1209
  const parentVoiceName = [...openElements].reverse().find((element) => element.voiceName)?.voiceName;
1210
1210
  const tokenName = nameMatch[1];
1211
+ const path = parent ? [...parent.path, `${tokenName}[${childElementIndex ?? 0}]`] : [tokenName];
1211
1212
  const tokenVoiceName = tokenName.toLowerCase() === "voice" ? attributes.get("name") : tokenName.toLowerCase() === "mstts:turn" ? attributes.get("voice") ?? parentVoiceName : parentVoiceName;
1212
1213
  tokens.push({
1213
1214
  attributes,
@@ -1218,12 +1219,14 @@ function tokenizeElements(source) {
1218
1219
  parentName: parent?.name,
1219
1220
  parentVoiceName,
1220
1221
  selfClosing,
1221
- start
1222
+ start,
1223
+ path
1222
1224
  });
1223
1225
  if (!selfClosing) {
1224
1226
  openElements.push({
1225
1227
  childElementCount: 0,
1226
1228
  name: tokenName,
1229
+ path,
1227
1230
  voiceName: tokenVoiceName
1228
1231
  });
1229
1232
  }
@@ -1236,13 +1239,14 @@ function location(source, offset) {
1236
1239
  const line = before.split("\n").length;
1237
1240
  return { line, column: before.length - (before.lastIndexOf("\n") + 1) + 1 };
1238
1241
  }
1239
- function addDiagnostic(diagnostics, source, offset, message, severity = "error", code2) {
1242
+ function addDiagnostic(diagnostics, source, offset, message, severity = "error", code2, metadata = {}) {
1240
1243
  diagnostics.push({
1241
1244
  ...location(source, offset),
1242
1245
  message,
1243
1246
  severity,
1244
1247
  source: "ssml-static-validator",
1245
- ...code2 ? { code: code2 } : {}
1248
+ ...code2 ? { code: code2 } : {},
1249
+ ...metadata
1246
1250
  });
1247
1251
  }
1248
1252
  function isSupportedProsodyRate(value) {
@@ -1705,9 +1709,11 @@ function validateAzureSsmlStatic(ssml, options = {}) {
1705
1709
  for (const token of tokens) {
1706
1710
  const tokenName = token.name.toLowerCase();
1707
1711
  const tokenVoiceName = tokenName === "voice" ? attr(token, "name")?.trim() : tokenName === "mstts:turn" ? attr(token, "voice")?.trim() || token.parentVoiceName : options.validateNestedVoices === false ? voiceName : token.parentVoiceName;
1712
+ const tokenDiagnosticStart = diagnostics.length;
1708
1713
  validateElement(token, ssml, diagnostics, tokenVoiceName, options, voiceCatalog);
1709
1714
  const definition = tokenVoiceName ? voiceCatalog.get(tokenVoiceName.toLowerCase()) : void 0;
1710
1715
  validateVoiceFeatureMatrix(token, ssml, diagnostics, tokenVoiceName, definition);
1716
+ annotateTokenDiagnostics(diagnostics, tokenDiagnosticStart, token, options, tokenVoiceName);
1711
1717
  if (tokenName === "voice" && options.model && definition?.models && !definition.models.some((model) => model.toLowerCase() === options.model?.toLowerCase())) {
1712
1718
  addDiagnostic(
1713
1719
  diagnostics,
@@ -1729,12 +1735,30 @@ function urlAttributes(token) {
1729
1735
  return value === void 0 ? [] : [{ attribute, value }];
1730
1736
  });
1731
1737
  }
1738
+ function annotateTokenDiagnostics(diagnostics, startIndex, token, options, voiceName) {
1739
+ const attributes = [...token.attributes.keys()];
1740
+ for (const diagnostic of diagnostics.slice(startIndex)) {
1741
+ const attributeName = attributes.find(
1742
+ (attribute) => new RegExp(`(?:<[^> ]+\\s+|")${attribute}(?:"|>|\\s)`, "i").test(diagnostic.message)
1743
+ );
1744
+ const nodePath = options.sourceNodePath ? [...options.sourceNodePath] : [...token.path];
1745
+ Object.assign(diagnostic, {
1746
+ range: { start: token.start, end: token.end + 1 },
1747
+ tagName: token.name,
1748
+ ...attributeName ? { attributeName } : {},
1749
+ ...voiceName ? { voiceName } : {},
1750
+ ...options.chunkIndex !== void 0 ? { chunkIndex: options.chunkIndex } : {},
1751
+ nodePath,
1752
+ targetNodePath: [...token.path]
1753
+ });
1754
+ }
1755
+ }
1732
1756
  function validateAzureSsml(ssml, options = {}) {
1733
1757
  const diagnostics = validateAzureSsmlStatic(ssml, options);
1734
1758
  const validator = options.urlValidator ?? options.customUrlValidator;
1735
1759
  if (!validator || typeof ssml !== "string") return diagnostics;
1736
1760
  const runnerOptions = options.urlValidation ?? {};
1737
- const boundedValidator = createAzureUrlValidatorRunner(validator, {
1761
+ const boundedValidator = options.urlValidatorRunner ?? createAzureUrlValidatorRunner(validator, {
1738
1762
  ...runnerOptions,
1739
1763
  ...options.urlValidatorConcurrency !== void 0 ? { concurrency: options.urlValidatorConcurrency } : {},
1740
1764
  ...options.urlValidatorTimeoutMs !== void 0 ? { timeoutMs: options.urlValidatorTimeoutMs } : {},
@@ -1759,21 +1783,25 @@ function validateAzureSsml(ssml, options = {}) {
1759
1783
  const valid = typeof result === "boolean" ? result : result.valid;
1760
1784
  if (!valid) {
1761
1785
  const reason = typeof result === "boolean" ? void 0 : result.reason;
1786
+ const diagnosticStart = diagnostics.length;
1762
1787
  addDiagnostic(
1763
1788
  diagnostics,
1764
1789
  ssml,
1765
1790
  token.start,
1766
1791
  `<${token.name} ${attribute}> was rejected by the custom URL validator${reason ? `: ${reason}` : "."}`
1767
1792
  );
1793
+ annotateTokenDiagnostics(diagnostics, diagnosticStart, token, options, token.parentVoiceName);
1768
1794
  }
1769
1795
  } catch (error) {
1770
1796
  const reason = error instanceof Error ? error.message : String(error);
1797
+ const diagnosticStart = diagnostics.length;
1771
1798
  addDiagnostic(
1772
1799
  diagnostics,
1773
1800
  ssml,
1774
1801
  token.start,
1775
1802
  `<${token.name} ${attribute}> could not be validated by the custom URL validator: ${reason}`
1776
1803
  );
1804
+ annotateTokenDiagnostics(diagnostics, diagnosticStart, token, options, token.parentVoiceName);
1777
1805
  }
1778
1806
  })
1779
1807
  );