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.
- package/dist/uss-xsd-engine.esm.js +198 -9
- package/dist/uss-xsd-engine.standalone.js +198 -9
- package/package.json +1 -1
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/*!
|
|
2
|
-
* uss-xsd-engine v0.1.
|
|
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
|
|
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 =
|
|
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
|
|
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
|
|
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.
|
|
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.
|
|
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
|
|
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 =
|
|
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
|
|
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
|
|
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.
|
|
2659
|
+
var ENGINE_VERSION = "v0.1.1";
|
|
2471
2660
|
|
|
2472
2661
|
// src/utils/result.js
|
|
2473
2662
|
function summarizeIssues(issues = []) {
|
package/package.json
CHANGED