uss-xsd-engine 0.1.0 → 0.1.1

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.
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * uss-xsd-engine v0.1.0
2
+ * uss-xsd-engine v0.1.1
3
3
  * (c) 2026 Bernard Mumble
4
4
  * MIT License
5
5
  */
@@ -1575,6 +1575,111 @@ function isImportNamespaceCompatible(ref, importedSchema) {
1575
1575
  }
1576
1576
  return (declaredNs || null) === (importedNs || null);
1577
1577
  }
1578
+ function normalizeSchemaPath(value) {
1579
+ if (!value || typeof value !== "string") return null;
1580
+ const trimmed = value.trim();
1581
+ if (!trimmed) return null;
1582
+ return trimmed.replace(/\\/g, "/").replace(/\/+/g, "/");
1583
+ }
1584
+ function getSchemaPathBasename(value) {
1585
+ const normalized = normalizeSchemaPath(value);
1586
+ if (!normalized) return null;
1587
+ const parts = normalized.split("/");
1588
+ return parts[parts.length - 1] || null;
1589
+ }
1590
+ function getExternalDocumentEntries(externalDocuments) {
1591
+ return Object.entries(externalDocuments || {}).map(([key, text]) => ({
1592
+ key,
1593
+ normalizedKey: normalizeSchemaPath(key),
1594
+ basename: getSchemaPathBasename(key),
1595
+ text
1596
+ }));
1597
+ }
1598
+ function getDeclaredTargetNamespaceFromText(xsdText) {
1599
+ if (typeof xsdText !== "string" || !xsdText.trim()) {
1600
+ return null;
1601
+ }
1602
+ try {
1603
+ const parser = new DOMParser();
1604
+ const doc = parser.parseFromString(xsdText, "application/xml");
1605
+ const parserError = doc.querySelector("parsererror");
1606
+ if (parserError) return null;
1607
+ const root = getSchemaRoot(doc);
1608
+ if (!root) return null;
1609
+ return root.hasAttribute("targetNamespace") ? root.getAttribute("targetNamespace") : null;
1610
+ } catch {
1611
+ return null;
1612
+ }
1613
+ }
1614
+ function resolveExternalDocument(ref, externalDocuments) {
1615
+ const entries = getExternalDocumentEntries(externalDocuments);
1616
+ const requestedLocation = ref?.schemaLocation || null;
1617
+ const normalizedRequestedLocation = normalizeSchemaPath(requestedLocation);
1618
+ const requestedBasename = getSchemaPathBasename(requestedLocation);
1619
+ if (requestedLocation && Object.prototype.hasOwnProperty.call(externalDocuments, requestedLocation)) {
1620
+ return {
1621
+ kind: "exact",
1622
+ entry: {
1623
+ key: requestedLocation,
1624
+ normalizedKey: normalizedRequestedLocation,
1625
+ basename: requestedBasename,
1626
+ text: externalDocuments[requestedLocation]
1627
+ },
1628
+ matches: []
1629
+ };
1630
+ }
1631
+ if (normalizedRequestedLocation) {
1632
+ const normalizedMatches = entries.filter(
1633
+ (entry) => entry.normalizedKey === normalizedRequestedLocation
1634
+ );
1635
+ if (normalizedMatches.length === 1) {
1636
+ return {
1637
+ kind: "normalized",
1638
+ entry: normalizedMatches[0],
1639
+ matches: normalizedMatches
1640
+ };
1641
+ }
1642
+ }
1643
+ if (requestedBasename) {
1644
+ const basenameMatches = entries.filter(
1645
+ (entry) => entry.basename === requestedBasename
1646
+ );
1647
+ if (basenameMatches.length === 1) {
1648
+ return {
1649
+ kind: "basename",
1650
+ entry: basenameMatches[0],
1651
+ matches: basenameMatches
1652
+ };
1653
+ }
1654
+ }
1655
+ if (ref?.kind === "import" && ref.namespace) {
1656
+ const namespaceMatches = entries.filter((entry) => {
1657
+ const declaredTargetNamespace = getDeclaredTargetNamespaceFromText(
1658
+ entry.text
1659
+ );
1660
+ return (declaredTargetNamespace || null) === (ref.namespace || null);
1661
+ });
1662
+ if (namespaceMatches.length === 1) {
1663
+ return {
1664
+ kind: "namespace",
1665
+ entry: namespaceMatches[0],
1666
+ matches: namespaceMatches
1667
+ };
1668
+ }
1669
+ if (namespaceMatches.length > 1) {
1670
+ return {
1671
+ kind: "ambiguous-namespace",
1672
+ entry: null,
1673
+ matches: namespaceMatches
1674
+ };
1675
+ }
1676
+ }
1677
+ return {
1678
+ kind: "not-found",
1679
+ entry: null,
1680
+ matches: []
1681
+ };
1682
+ }
1578
1683
  function buildSchemaModel(doc, options = {}) {
1579
1684
  const issues = [];
1580
1685
  const schema = createEmptySchemaModel();
@@ -1773,11 +1878,34 @@ function buildSchemaModel(doc, options = {}) {
1773
1878
  const imports = schema.externalRefs.imports || [];
1774
1879
  for (const ref of [...includes, ...imports]) {
1775
1880
  if (!ref.schemaLocation) continue;
1776
- const visitKey = ref.kind === "include" && schema.targetNamespace ? `${ref.schemaLocation}::include::${schema.targetNamespace}` : ref.schemaLocation;
1881
+ const resolution = resolveExternalDocument(ref, externalDocuments);
1882
+ if (resolution.kind === "ambiguous-namespace") {
1883
+ issues.push(
1884
+ createIssue({
1885
+ code: ISSUE_CODES.XSD_IMPORT_NOT_PROVIDED,
1886
+ severity: "error",
1887
+ message: `Multiple provided schemas match xs:import namespace '${ref.namespace || ""}'. Unable to determine which schema to use.`,
1888
+ line: ref.line,
1889
+ column: ref.column,
1890
+ path: ref.path,
1891
+ source: "xsd",
1892
+ nodeKind: ref.kind,
1893
+ details: {
1894
+ schemaLocation: ref.schemaLocation,
1895
+ namespace: ref.namespace,
1896
+ matchingKeys: resolution.matches.map((match) => match.key)
1897
+ }
1898
+ })
1899
+ );
1900
+ continue;
1901
+ }
1902
+ const resolvedEntry = resolution.entry;
1903
+ const resolvedSchemaKey = resolvedEntry?.key || ref.schemaLocation;
1904
+ const visitKey = ref.kind === "include" && schema.targetNamespace ? `${resolvedSchemaKey}::include::${schema.targetNamespace}` : resolvedSchemaKey;
1777
1905
  if (visited.has(visitKey)) {
1778
1906
  continue;
1779
1907
  }
1780
- const externalXsdText = externalDocuments[ref.schemaLocation];
1908
+ const externalXsdText = resolvedEntry?.text || null;
1781
1909
  if (!externalXsdText) {
1782
1910
  issues.push(
1783
1911
  createIssue({
@@ -1820,9 +1948,6 @@ function buildSchemaModel(doc, options = {}) {
1820
1948
  ...shouldApplyChameleonInclude ? { _overrideTargetNamespace: schema.targetNamespace } : {}
1821
1949
  });
1822
1950
  if (externalBuild.schema) {
1823
- if (ref.kind === "import") {
1824
- schema.importedSchemas.push(externalBuild.schema);
1825
- }
1826
1951
  if (ref.kind === "include") {
1827
1952
  if (!isIncludeNamespaceCompatible(schema, externalBuild.schema)) {
1828
1953
  issues.push(
@@ -1837,6 +1962,8 @@ function buildSchemaModel(doc, options = {}) {
1837
1962
  nodeKind: "include",
1838
1963
  details: {
1839
1964
  schemaLocation: ref.schemaLocation,
1965
+ resolvedSchemaKey,
1966
+ resolutionKind: resolution.kind,
1840
1967
  hostTargetNamespace: schema.targetNamespace || null,
1841
1968
  includedTargetNamespace: externalBuild.schema.targetNamespace || null,
1842
1969
  includedDeclaredTargetNamespace: externalDeclaredTargetNamespace,
@@ -1866,6 +1993,8 @@ function buildSchemaModel(doc, options = {}) {
1866
1993
  nodeKind: "import",
1867
1994
  details: {
1868
1995
  schemaLocation: ref.schemaLocation,
1996
+ resolvedSchemaKey,
1997
+ resolutionKind: resolution.kind,
1869
1998
  declaredNamespace: ref.namespace || null,
1870
1999
  importedTargetNamespace: externalBuild.schema.targetNamespace || null
1871
2000
  }
@@ -2204,12 +2333,72 @@ function runDefaultFixedDiagnostics(schema) {
2204
2333
  }
2205
2334
 
2206
2335
  // src/diagnostics/schemaImportDiagnostics.js
2336
+ function normalizeSchemaPath2(value) {
2337
+ if (!value || typeof value !== "string") return null;
2338
+ const trimmed = value.trim();
2339
+ if (!trimmed) return null;
2340
+ return trimmed.replace(/\\/g, "/").replace(/\/+/g, "/");
2341
+ }
2342
+ function getSchemaPathBasename2(value) {
2343
+ const normalized = normalizeSchemaPath2(value);
2344
+ if (!normalized) return null;
2345
+ const parts = normalized.split("/");
2346
+ return parts[parts.length - 1] || null;
2347
+ }
2348
+ function getExternalDocumentEntries2(externalDocuments) {
2349
+ return Object.entries(externalDocuments || {}).map(([key, text]) => ({
2350
+ key,
2351
+ normalizedKey: normalizeSchemaPath2(key),
2352
+ basename: getSchemaPathBasename2(key),
2353
+ text
2354
+ }));
2355
+ }
2356
+ function getDeclaredTargetNamespaceFromText2(xsdText) {
2357
+ if (typeof xsdText !== "string" || !xsdText.trim()) {
2358
+ return null;
2359
+ }
2360
+ try {
2361
+ const parser = new DOMParser();
2362
+ const doc = parser.parseFromString(xsdText, "application/xml");
2363
+ const parserError = doc.querySelector("parsererror");
2364
+ if (parserError) return null;
2365
+ const root = doc?.documentElement || null;
2366
+ if (!root || root.localName !== "schema") return null;
2367
+ return root.hasAttribute("targetNamespace") ? root.getAttribute("targetNamespace") : null;
2368
+ } catch {
2369
+ return null;
2370
+ }
2371
+ }
2372
+ function hasMatchingExternalDocument(ref, externalDocuments) {
2373
+ const entries = getExternalDocumentEntries2(externalDocuments);
2374
+ const requestedLocation = ref?.schemaLocation || null;
2375
+ const normalizedRequestedLocation = normalizeSchemaPath2(requestedLocation);
2376
+ const requestedBasename = getSchemaPathBasename2(requestedLocation);
2377
+ if (requestedLocation && Object.prototype.hasOwnProperty.call(externalDocuments, requestedLocation)) {
2378
+ return true;
2379
+ }
2380
+ if (normalizedRequestedLocation && entries.some((entry) => entry.normalizedKey === normalizedRequestedLocation)) {
2381
+ return true;
2382
+ }
2383
+ if (requestedBasename && entries.some((entry) => entry.basename === requestedBasename)) {
2384
+ return true;
2385
+ }
2386
+ if (ref?.kind === "import" && ref.namespace) {
2387
+ return entries.some((entry) => {
2388
+ const declaredTargetNamespace = getDeclaredTargetNamespaceFromText2(
2389
+ entry.text
2390
+ );
2391
+ return (declaredTargetNamespace || null) === (ref.namespace || null);
2392
+ });
2393
+ }
2394
+ return false;
2395
+ }
2207
2396
  function runImportDiagnostics(schema, options = {}) {
2208
2397
  const issues = [];
2209
2398
  const externalDocuments = options.externalDocuments || {};
2210
2399
  for (const ref of schema.externalRefs.includes || []) {
2211
2400
  if (!ref.schemaLocation) continue;
2212
- if (externalDocuments[ref.schemaLocation]) continue;
2401
+ if (hasMatchingExternalDocument(ref, externalDocuments)) continue;
2213
2402
  issues.push(
2214
2403
  createIssue({
2215
2404
  code: ISSUE_CODES.XSD_INCLUDE_NOT_PROVIDED,
@@ -2229,7 +2418,7 @@ function runImportDiagnostics(schema, options = {}) {
2229
2418
  }
2230
2419
  for (const ref of schema.externalRefs.imports || []) {
2231
2420
  if (!ref.schemaLocation) continue;
2232
- if (externalDocuments[ref.schemaLocation]) continue;
2421
+ if (hasMatchingExternalDocument(ref, externalDocuments)) continue;
2233
2422
  issues.push(
2234
2423
  createIssue({
2235
2424
  code: ISSUE_CODES.XSD_IMPORT_NOT_PROVIDED,
@@ -2440,7 +2629,7 @@ function runSchemaDiagnostics(schema, options = {}) {
2440
2629
  }
2441
2630
 
2442
2631
  // src/version.js
2443
- var ENGINE_VERSION = "v0.1.0";
2632
+ var ENGINE_VERSION = "v0.1.1";
2444
2633
 
2445
2634
  // src/utils/result.js
2446
2635
  function summarizeIssues(issues = []) {
@@ -1,5 +1,5 @@
1
1
  /*!
2
- * uss-xsd-engine v0.1.0
2
+ * uss-xsd-engine v0.1.1
3
3
  * (c) 2026 Bernard Mumble
4
4
  * MIT License
5
5
  */
@@ -1602,6 +1602,111 @@ var UssXsdEngine = (() => {
1602
1602
  }
1603
1603
  return (declaredNs || null) === (importedNs || null);
1604
1604
  }
1605
+ function normalizeSchemaPath(value) {
1606
+ if (!value || typeof value !== "string") return null;
1607
+ const trimmed = value.trim();
1608
+ if (!trimmed) return null;
1609
+ return trimmed.replace(/\\/g, "/").replace(/\/+/g, "/");
1610
+ }
1611
+ function getSchemaPathBasename(value) {
1612
+ const normalized = normalizeSchemaPath(value);
1613
+ if (!normalized) return null;
1614
+ const parts = normalized.split("/");
1615
+ return parts[parts.length - 1] || null;
1616
+ }
1617
+ function getExternalDocumentEntries(externalDocuments) {
1618
+ return Object.entries(externalDocuments || {}).map(([key, text]) => ({
1619
+ key,
1620
+ normalizedKey: normalizeSchemaPath(key),
1621
+ basename: getSchemaPathBasename(key),
1622
+ text
1623
+ }));
1624
+ }
1625
+ function getDeclaredTargetNamespaceFromText(xsdText) {
1626
+ if (typeof xsdText !== "string" || !xsdText.trim()) {
1627
+ return null;
1628
+ }
1629
+ try {
1630
+ const parser = new DOMParser();
1631
+ const doc = parser.parseFromString(xsdText, "application/xml");
1632
+ const parserError = doc.querySelector("parsererror");
1633
+ if (parserError) return null;
1634
+ const root = getSchemaRoot(doc);
1635
+ if (!root) return null;
1636
+ return root.hasAttribute("targetNamespace") ? root.getAttribute("targetNamespace") : null;
1637
+ } catch {
1638
+ return null;
1639
+ }
1640
+ }
1641
+ function resolveExternalDocument(ref, externalDocuments) {
1642
+ const entries = getExternalDocumentEntries(externalDocuments);
1643
+ const requestedLocation = ref?.schemaLocation || null;
1644
+ const normalizedRequestedLocation = normalizeSchemaPath(requestedLocation);
1645
+ const requestedBasename = getSchemaPathBasename(requestedLocation);
1646
+ if (requestedLocation && Object.prototype.hasOwnProperty.call(externalDocuments, requestedLocation)) {
1647
+ return {
1648
+ kind: "exact",
1649
+ entry: {
1650
+ key: requestedLocation,
1651
+ normalizedKey: normalizedRequestedLocation,
1652
+ basename: requestedBasename,
1653
+ text: externalDocuments[requestedLocation]
1654
+ },
1655
+ matches: []
1656
+ };
1657
+ }
1658
+ if (normalizedRequestedLocation) {
1659
+ const normalizedMatches = entries.filter(
1660
+ (entry) => entry.normalizedKey === normalizedRequestedLocation
1661
+ );
1662
+ if (normalizedMatches.length === 1) {
1663
+ return {
1664
+ kind: "normalized",
1665
+ entry: normalizedMatches[0],
1666
+ matches: normalizedMatches
1667
+ };
1668
+ }
1669
+ }
1670
+ if (requestedBasename) {
1671
+ const basenameMatches = entries.filter(
1672
+ (entry) => entry.basename === requestedBasename
1673
+ );
1674
+ if (basenameMatches.length === 1) {
1675
+ return {
1676
+ kind: "basename",
1677
+ entry: basenameMatches[0],
1678
+ matches: basenameMatches
1679
+ };
1680
+ }
1681
+ }
1682
+ if (ref?.kind === "import" && ref.namespace) {
1683
+ const namespaceMatches = entries.filter((entry) => {
1684
+ const declaredTargetNamespace = getDeclaredTargetNamespaceFromText(
1685
+ entry.text
1686
+ );
1687
+ return (declaredTargetNamespace || null) === (ref.namespace || null);
1688
+ });
1689
+ if (namespaceMatches.length === 1) {
1690
+ return {
1691
+ kind: "namespace",
1692
+ entry: namespaceMatches[0],
1693
+ matches: namespaceMatches
1694
+ };
1695
+ }
1696
+ if (namespaceMatches.length > 1) {
1697
+ return {
1698
+ kind: "ambiguous-namespace",
1699
+ entry: null,
1700
+ matches: namespaceMatches
1701
+ };
1702
+ }
1703
+ }
1704
+ return {
1705
+ kind: "not-found",
1706
+ entry: null,
1707
+ matches: []
1708
+ };
1709
+ }
1605
1710
  function buildSchemaModel(doc, options = {}) {
1606
1711
  const issues = [];
1607
1712
  const schema = createEmptySchemaModel();
@@ -1800,11 +1905,34 @@ var UssXsdEngine = (() => {
1800
1905
  const imports = schema.externalRefs.imports || [];
1801
1906
  for (const ref of [...includes, ...imports]) {
1802
1907
  if (!ref.schemaLocation) continue;
1803
- const visitKey = ref.kind === "include" && schema.targetNamespace ? `${ref.schemaLocation}::include::${schema.targetNamespace}` : ref.schemaLocation;
1908
+ const resolution = resolveExternalDocument(ref, externalDocuments);
1909
+ if (resolution.kind === "ambiguous-namespace") {
1910
+ issues.push(
1911
+ createIssue({
1912
+ code: ISSUE_CODES.XSD_IMPORT_NOT_PROVIDED,
1913
+ severity: "error",
1914
+ message: `Multiple provided schemas match xs:import namespace '${ref.namespace || ""}'. Unable to determine which schema to use.`,
1915
+ line: ref.line,
1916
+ column: ref.column,
1917
+ path: ref.path,
1918
+ source: "xsd",
1919
+ nodeKind: ref.kind,
1920
+ details: {
1921
+ schemaLocation: ref.schemaLocation,
1922
+ namespace: ref.namespace,
1923
+ matchingKeys: resolution.matches.map((match) => match.key)
1924
+ }
1925
+ })
1926
+ );
1927
+ continue;
1928
+ }
1929
+ const resolvedEntry = resolution.entry;
1930
+ const resolvedSchemaKey = resolvedEntry?.key || ref.schemaLocation;
1931
+ const visitKey = ref.kind === "include" && schema.targetNamespace ? `${resolvedSchemaKey}::include::${schema.targetNamespace}` : resolvedSchemaKey;
1804
1932
  if (visited.has(visitKey)) {
1805
1933
  continue;
1806
1934
  }
1807
- const externalXsdText = externalDocuments[ref.schemaLocation];
1935
+ const externalXsdText = resolvedEntry?.text || null;
1808
1936
  if (!externalXsdText) {
1809
1937
  issues.push(
1810
1938
  createIssue({
@@ -1847,9 +1975,6 @@ var UssXsdEngine = (() => {
1847
1975
  ...shouldApplyChameleonInclude ? { _overrideTargetNamespace: schema.targetNamespace } : {}
1848
1976
  });
1849
1977
  if (externalBuild.schema) {
1850
- if (ref.kind === "import") {
1851
- schema.importedSchemas.push(externalBuild.schema);
1852
- }
1853
1978
  if (ref.kind === "include") {
1854
1979
  if (!isIncludeNamespaceCompatible(schema, externalBuild.schema)) {
1855
1980
  issues.push(
@@ -1864,6 +1989,8 @@ var UssXsdEngine = (() => {
1864
1989
  nodeKind: "include",
1865
1990
  details: {
1866
1991
  schemaLocation: ref.schemaLocation,
1992
+ resolvedSchemaKey,
1993
+ resolutionKind: resolution.kind,
1867
1994
  hostTargetNamespace: schema.targetNamespace || null,
1868
1995
  includedTargetNamespace: externalBuild.schema.targetNamespace || null,
1869
1996
  includedDeclaredTargetNamespace: externalDeclaredTargetNamespace,
@@ -1893,6 +2020,8 @@ var UssXsdEngine = (() => {
1893
2020
  nodeKind: "import",
1894
2021
  details: {
1895
2022
  schemaLocation: ref.schemaLocation,
2023
+ resolvedSchemaKey,
2024
+ resolutionKind: resolution.kind,
1896
2025
  declaredNamespace: ref.namespace || null,
1897
2026
  importedTargetNamespace: externalBuild.schema.targetNamespace || null
1898
2027
  }
@@ -2231,12 +2360,72 @@ var UssXsdEngine = (() => {
2231
2360
  }
2232
2361
 
2233
2362
  // src/diagnostics/schemaImportDiagnostics.js
2363
+ function normalizeSchemaPath2(value) {
2364
+ if (!value || typeof value !== "string") return null;
2365
+ const trimmed = value.trim();
2366
+ if (!trimmed) return null;
2367
+ return trimmed.replace(/\\/g, "/").replace(/\/+/g, "/");
2368
+ }
2369
+ function getSchemaPathBasename2(value) {
2370
+ const normalized = normalizeSchemaPath2(value);
2371
+ if (!normalized) return null;
2372
+ const parts = normalized.split("/");
2373
+ return parts[parts.length - 1] || null;
2374
+ }
2375
+ function getExternalDocumentEntries2(externalDocuments) {
2376
+ return Object.entries(externalDocuments || {}).map(([key, text]) => ({
2377
+ key,
2378
+ normalizedKey: normalizeSchemaPath2(key),
2379
+ basename: getSchemaPathBasename2(key),
2380
+ text
2381
+ }));
2382
+ }
2383
+ function getDeclaredTargetNamespaceFromText2(xsdText) {
2384
+ if (typeof xsdText !== "string" || !xsdText.trim()) {
2385
+ return null;
2386
+ }
2387
+ try {
2388
+ const parser = new DOMParser();
2389
+ const doc = parser.parseFromString(xsdText, "application/xml");
2390
+ const parserError = doc.querySelector("parsererror");
2391
+ if (parserError) return null;
2392
+ const root = doc?.documentElement || null;
2393
+ if (!root || root.localName !== "schema") return null;
2394
+ return root.hasAttribute("targetNamespace") ? root.getAttribute("targetNamespace") : null;
2395
+ } catch {
2396
+ return null;
2397
+ }
2398
+ }
2399
+ function hasMatchingExternalDocument(ref, externalDocuments) {
2400
+ const entries = getExternalDocumentEntries2(externalDocuments);
2401
+ const requestedLocation = ref?.schemaLocation || null;
2402
+ const normalizedRequestedLocation = normalizeSchemaPath2(requestedLocation);
2403
+ const requestedBasename = getSchemaPathBasename2(requestedLocation);
2404
+ if (requestedLocation && Object.prototype.hasOwnProperty.call(externalDocuments, requestedLocation)) {
2405
+ return true;
2406
+ }
2407
+ if (normalizedRequestedLocation && entries.some((entry) => entry.normalizedKey === normalizedRequestedLocation)) {
2408
+ return true;
2409
+ }
2410
+ if (requestedBasename && entries.some((entry) => entry.basename === requestedBasename)) {
2411
+ return true;
2412
+ }
2413
+ if (ref?.kind === "import" && ref.namespace) {
2414
+ return entries.some((entry) => {
2415
+ const declaredTargetNamespace = getDeclaredTargetNamespaceFromText2(
2416
+ entry.text
2417
+ );
2418
+ return (declaredTargetNamespace || null) === (ref.namespace || null);
2419
+ });
2420
+ }
2421
+ return false;
2422
+ }
2234
2423
  function runImportDiagnostics(schema, options = {}) {
2235
2424
  const issues = [];
2236
2425
  const externalDocuments = options.externalDocuments || {};
2237
2426
  for (const ref of schema.externalRefs.includes || []) {
2238
2427
  if (!ref.schemaLocation) continue;
2239
- if (externalDocuments[ref.schemaLocation]) continue;
2428
+ if (hasMatchingExternalDocument(ref, externalDocuments)) continue;
2240
2429
  issues.push(
2241
2430
  createIssue({
2242
2431
  code: ISSUE_CODES.XSD_INCLUDE_NOT_PROVIDED,
@@ -2256,7 +2445,7 @@ var UssXsdEngine = (() => {
2256
2445
  }
2257
2446
  for (const ref of schema.externalRefs.imports || []) {
2258
2447
  if (!ref.schemaLocation) continue;
2259
- if (externalDocuments[ref.schemaLocation]) continue;
2448
+ if (hasMatchingExternalDocument(ref, externalDocuments)) continue;
2260
2449
  issues.push(
2261
2450
  createIssue({
2262
2451
  code: ISSUE_CODES.XSD_IMPORT_NOT_PROVIDED,
@@ -2467,7 +2656,7 @@ var UssXsdEngine = (() => {
2467
2656
  }
2468
2657
 
2469
2658
  // src/version.js
2470
- var ENGINE_VERSION = "v0.1.0";
2659
+ var ENGINE_VERSION = "v0.1.1";
2471
2660
 
2472
2661
  // src/utils/result.js
2473
2662
  function summarizeIssues(issues = []) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "uss-xsd-engine",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Browser-first XSD engine for schema diagnostics, tree extraction, sample XML generation, and XML validation.",
5
5
  "type": "module",
6
6
  "main": "dist/uss-xsd-engine.esm.js",