@adrk/mxls 1.0.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.
Files changed (112) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +110 -0
  3. package/dist/completion/CompletionBuilder.d.ts +26 -0
  4. package/dist/completion/CompletionBuilder.d.ts.map +1 -0
  5. package/dist/completion/CompletionBuilder.js +113 -0
  6. package/dist/completion/CompletionBuilder.js.map +1 -0
  7. package/dist/completion/CompletionCache.d.ts +16 -0
  8. package/dist/completion/CompletionCache.d.ts.map +1 -0
  9. package/dist/completion/CompletionCache.js +25 -0
  10. package/dist/completion/CompletionCache.js.map +1 -0
  11. package/dist/completion/NamespaceResolver.d.ts +21 -0
  12. package/dist/completion/NamespaceResolver.d.ts.map +1 -0
  13. package/dist/completion/NamespaceResolver.js +58 -0
  14. package/dist/completion/NamespaceResolver.js.map +1 -0
  15. package/dist/completion/SchemaCompleter.d.ts +23 -0
  16. package/dist/completion/SchemaCompleter.d.ts.map +1 -0
  17. package/dist/completion/SchemaCompleter.js +164 -0
  18. package/dist/completion/SchemaCompleter.js.map +1 -0
  19. package/dist/completion/TextAnalyzer.d.ts +34 -0
  20. package/dist/completion/TextAnalyzer.d.ts.map +1 -0
  21. package/dist/completion/TextAnalyzer.js +122 -0
  22. package/dist/completion/TextAnalyzer.js.map +1 -0
  23. package/dist/features/EditorPlugin.d.ts +49 -0
  24. package/dist/features/EditorPlugin.d.ts.map +1 -0
  25. package/dist/features/EditorPlugin.js +128 -0
  26. package/dist/features/EditorPlugin.js.map +1 -0
  27. package/dist/formatter/XmlFormatter.d.ts +4 -0
  28. package/dist/formatter/XmlFormatter.d.ts.map +1 -0
  29. package/dist/formatter/XmlFormatter.js +13 -0
  30. package/dist/formatter/XmlFormatter.js.map +1 -0
  31. package/dist/hover/HoverBuilder.d.ts +8 -0
  32. package/dist/hover/HoverBuilder.d.ts.map +1 -0
  33. package/dist/hover/HoverBuilder.js +27 -0
  34. package/dist/hover/HoverBuilder.js.map +1 -0
  35. package/dist/hover/SchemaHover.d.ts +12 -0
  36. package/dist/hover/SchemaHover.d.ts.map +1 -0
  37. package/dist/hover/SchemaHover.js +71 -0
  38. package/dist/hover/SchemaHover.js.map +1 -0
  39. package/dist/index.d.ts +14 -0
  40. package/dist/index.d.ts.map +1 -0
  41. package/dist/index.js +9 -0
  42. package/dist/index.js.map +1 -0
  43. package/dist/interfaces/IMonacoApi.d.ts +39 -0
  44. package/dist/interfaces/IMonacoApi.d.ts.map +1 -0
  45. package/dist/interfaces/IMonacoApi.js +2 -0
  46. package/dist/interfaces/IMonacoApi.js.map +1 -0
  47. package/dist/interfaces/ISchemaParser.d.ts +30 -0
  48. package/dist/interfaces/ISchemaParser.d.ts.map +1 -0
  49. package/dist/interfaces/ISchemaParser.js +2 -0
  50. package/dist/interfaces/ISchemaParser.js.map +1 -0
  51. package/dist/interfaces/ISchemaRegistry.d.ts +46 -0
  52. package/dist/interfaces/ISchemaRegistry.d.ts.map +1 -0
  53. package/dist/interfaces/ISchemaRegistry.js +2 -0
  54. package/dist/interfaces/ISchemaRegistry.js.map +1 -0
  55. package/dist/interfaces/ISchemaWorker.d.ts +25 -0
  56. package/dist/interfaces/ISchemaWorker.d.ts.map +1 -0
  57. package/dist/interfaces/ISchemaWorker.js +2 -0
  58. package/dist/interfaces/ISchemaWorker.js.map +1 -0
  59. package/dist/manager/SchemaRegistry.d.ts +24 -0
  60. package/dist/manager/SchemaRegistry.d.ts.map +1 -0
  61. package/dist/manager/SchemaRegistry.js +84 -0
  62. package/dist/manager/SchemaRegistry.js.map +1 -0
  63. package/dist/manager/SchemaWorker.d.ts +25 -0
  64. package/dist/manager/SchemaWorker.d.ts.map +1 -0
  65. package/dist/manager/SchemaWorker.js +70 -0
  66. package/dist/manager/SchemaWorker.js.map +1 -0
  67. package/dist/parser/SchemaIndex.d.ts +54 -0
  68. package/dist/parser/SchemaIndex.d.ts.map +1 -0
  69. package/dist/parser/SchemaIndex.js +149 -0
  70. package/dist/parser/SchemaIndex.js.map +1 -0
  71. package/dist/parser/SchemaParser.d.ts +23 -0
  72. package/dist/parser/SchemaParser.d.ts.map +1 -0
  73. package/dist/parser/SchemaParser.js +44 -0
  74. package/dist/parser/SchemaParser.js.map +1 -0
  75. package/dist/parser/SchemaQuery.d.ts +38 -0
  76. package/dist/parser/SchemaQuery.d.ts.map +1 -0
  77. package/dist/parser/SchemaQuery.js +364 -0
  78. package/dist/parser/SchemaQuery.js.map +1 -0
  79. package/dist/template/TemplateBuilder.d.ts +18 -0
  80. package/dist/template/TemplateBuilder.d.ts.map +1 -0
  81. package/dist/template/TemplateBuilder.js +52 -0
  82. package/dist/template/TemplateBuilder.js.map +1 -0
  83. package/dist/types.d.ts +81 -0
  84. package/dist/types.d.ts.map +1 -0
  85. package/dist/types.js +27 -0
  86. package/dist/types.js.map +1 -0
  87. package/dist/utils/Logger.d.ts +17 -0
  88. package/dist/utils/Logger.d.ts.map +1 -0
  89. package/dist/utils/Logger.js +41 -0
  90. package/dist/utils/Logger.js.map +1 -0
  91. package/dist/utils/XmlTextUtils.d.ts +20 -0
  92. package/dist/utils/XmlTextUtils.d.ts.map +1 -0
  93. package/dist/utils/XmlTextUtils.js +85 -0
  94. package/dist/utils/XmlTextUtils.js.map +1 -0
  95. package/dist/validation/DecorationMapper.d.ts +15 -0
  96. package/dist/validation/DecorationMapper.d.ts.map +1 -0
  97. package/dist/validation/DecorationMapper.js +59 -0
  98. package/dist/validation/DecorationMapper.js.map +1 -0
  99. package/dist/validation/SchemaDecorator.d.ts +26 -0
  100. package/dist/validation/SchemaDecorator.d.ts.map +1 -0
  101. package/dist/validation/SchemaDecorator.js +50 -0
  102. package/dist/validation/SchemaDecorator.js.map +1 -0
  103. package/dist/validation/SchemaValidator.d.ts +13 -0
  104. package/dist/validation/SchemaValidator.d.ts.map +1 -0
  105. package/dist/validation/SchemaValidator.js +387 -0
  106. package/dist/validation/SchemaValidator.js.map +1 -0
  107. package/dist/validation/validation.worker.d.ts +2 -0
  108. package/dist/validation/validation.worker.d.ts.map +1 -0
  109. package/dist/validation/validation.worker.js +57 -0
  110. package/dist/validation/validation.worker.js.map +1 -0
  111. package/package.json +49 -0
  112. package/style.css +17 -0
package/dist/types.js ADDED
@@ -0,0 +1,27 @@
1
+ // ─── Schema shape ─────────────────────────────────────────────────────────────
2
+ export const ContentModelType = {
3
+ sequence: 'sequence',
4
+ choice: 'choice',
5
+ all: 'all',
6
+ simpleContent: 'simpleContent',
7
+ };
8
+ // ─── Completion ───────────────────────────────────────────────────────────────
9
+ export var CompletionType;
10
+ (function (CompletionType) {
11
+ CompletionType[CompletionType["none"] = 0] = "none";
12
+ CompletionType[CompletionType["element"] = 1] = "element";
13
+ CompletionType[CompletionType["attribute"] = 2] = "attribute";
14
+ CompletionType[CompletionType["incompleteElement"] = 3] = "incompleteElement";
15
+ CompletionType[CompletionType["closingElement"] = 4] = "closingElement";
16
+ CompletionType[CompletionType["snippet"] = 5] = "snippet";
17
+ CompletionType[CompletionType["incompleteAttribute"] = 6] = "incompleteAttribute";
18
+ CompletionType[CompletionType["attributeValue"] = 7] = "attributeValue";
19
+ })(CompletionType || (CompletionType = {}));
20
+ // ─── Validation ───────────────────────────────────────────────────────────────
21
+ export var Severity;
22
+ (function (Severity) {
23
+ Severity["warning"] = "warning";
24
+ Severity["error"] = "error";
25
+ Severity["fatalError"] = "fatalError";
26
+ })(Severity || (Severity = {}));
27
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAgBA,iFAAiF;AAEjF,MAAM,CAAC,MAAM,gBAAgB,GAAG;IAC5B,QAAQ,EAAE,UAAU;IACpB,MAAM,EAAE,QAAQ;IAChB,GAAG,EAAE,KAAK;IACV,aAAa,EAAE,eAAe;CACxB,CAAA;AAiBV,iFAAiF;AAEjF,MAAM,CAAN,IAAY,cASX;AATD,WAAY,cAAc;IACtB,mDAAI,CAAA;IACJ,yDAAO,CAAA;IACP,6DAAS,CAAA;IACT,6EAAiB,CAAA;IACjB,uEAAc,CAAA;IACd,yDAAO,CAAA;IACP,iFAAmB,CAAA;IACnB,uEAAc,CAAA;AAClB,CAAC,EATW,cAAc,KAAd,cAAc,QASzB;AA6BD,iFAAiF;AAEjF,MAAM,CAAN,IAAY,QAIX;AAJD,WAAY,QAAQ;IAChB,+BAAmB,CAAA;IACnB,2BAAe,CAAA;IACf,qCAAyB,CAAA;AAC7B,CAAC,EAJW,QAAQ,KAAR,QAAQ,QAInB"}
@@ -0,0 +1,17 @@
1
+ export type LogLevel = 'none' | 'error' | 'warn' | 'info' | 'debug' | 'verbose';
2
+ declare class MxlsLogger {
3
+ private level;
4
+ setLevel(level: LogLevel): void;
5
+ getLevel(): LogLevel;
6
+ private enabled;
7
+ error(msg: string, ...args: unknown[]): void;
8
+ warn(msg: string, ...args: unknown[]): void;
9
+ info(msg: string, ...args: unknown[]): void;
10
+ debug(msg: string, ...args: unknown[]): void;
11
+ verbose(msg: string, ...args: unknown[]): void;
12
+ }
13
+ export declare const logger: MxlsLogger;
14
+ /** Set the global log level for the mxls library. Default is 'none' (silent). */
15
+ export declare function setLogLevel(level: LogLevel): void;
16
+ export {};
17
+ //# sourceMappingURL=Logger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Logger.d.ts","sourceRoot":"","sources":["../../src/utils/Logger.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,QAAQ,GAAG,MAAM,GAAG,OAAO,GAAG,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,SAAS,CAAA;AAM/E,cAAM,UAAU;IACZ,OAAO,CAAC,KAAK,CAAmB;IAEhC,QAAQ,CAAC,KAAK,EAAE,QAAQ,GAAG,IAAI;IAI/B,QAAQ,IAAI,QAAQ;IAIpB,OAAO,CAAC,OAAO;IAIf,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI;IAI5C,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI;IAI3C,IAAI,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI;IAI3C,KAAK,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI;IAI5C,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,IAAI,EAAE,OAAO,EAAE,GAAG,IAAI;CAGjD;AAED,eAAO,MAAM,MAAM,YAAmB,CAAA;AAEtC,iFAAiF;AACjF,wBAAgB,WAAW,CAAC,KAAK,EAAE,QAAQ,GAAG,IAAI,CAEjD"}
@@ -0,0 +1,41 @@
1
+ const RANK = {
2
+ none: 0, error: 1, warn: 2, info: 3, debug: 4, verbose: 5,
3
+ };
4
+ class MxlsLogger {
5
+ level = 'none';
6
+ setLevel(level) {
7
+ this.level = level;
8
+ }
9
+ getLevel() {
10
+ return this.level;
11
+ }
12
+ enabled(level) {
13
+ return RANK[this.level] >= RANK[level];
14
+ }
15
+ error(msg, ...args) {
16
+ if (this.enabled('error'))
17
+ console.error(`[mxls] ERROR ${msg}`, ...args);
18
+ }
19
+ warn(msg, ...args) {
20
+ if (this.enabled('warn'))
21
+ console.warn(`[mxls] WARN ${msg}`, ...args);
22
+ }
23
+ info(msg, ...args) {
24
+ if (this.enabled('info'))
25
+ console.info(`[mxls] INFO ${msg}`, ...args);
26
+ }
27
+ debug(msg, ...args) {
28
+ if (this.enabled('debug'))
29
+ console.debug(`[mxls] DEBUG ${msg}`, ...args);
30
+ }
31
+ verbose(msg, ...args) {
32
+ if (this.enabled('verbose'))
33
+ console.debug(`[mxls] TRACE ${msg}`, ...args);
34
+ }
35
+ }
36
+ export const logger = new MxlsLogger();
37
+ /** Set the global log level for the mxls library. Default is 'none' (silent). */
38
+ export function setLogLevel(level) {
39
+ logger.setLevel(level);
40
+ }
41
+ //# sourceMappingURL=Logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Logger.js","sourceRoot":"","sources":["../../src/utils/Logger.ts"],"names":[],"mappings":"AAEA,MAAM,IAAI,GAA6B;IACnC,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC;CAC5D,CAAA;AAED,MAAM,UAAU;IACJ,KAAK,GAAa,MAAM,CAAA;IAEhC,QAAQ,CAAC,KAAe;QACpB,IAAI,CAAC,KAAK,GAAG,KAAK,CAAA;IACtB,CAAC;IAED,QAAQ;QACJ,OAAO,IAAI,CAAC,KAAK,CAAA;IACrB,CAAC;IAEO,OAAO,CAAC,KAAe;QAC3B,OAAO,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,CAAA;IAC1C,CAAC;IAED,KAAK,CAAC,GAAW,EAAE,GAAG,IAAe;QACjC,IAAI,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC;YAAE,OAAO,CAAC,KAAK,CAAC,gBAAgB,GAAG,EAAE,EAAE,GAAG,IAAI,CAAC,CAAA;IAC5E,CAAC;IAED,IAAI,CAAC,GAAW,EAAE,GAAG,IAAe;QAChC,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC;YAAE,OAAO,CAAC,IAAI,CAAC,gBAAgB,GAAG,EAAE,EAAE,GAAG,IAAI,CAAC,CAAA;IAC1E,CAAC;IAED,IAAI,CAAC,GAAW,EAAE,GAAG,IAAe;QAChC,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,CAAC;YAAE,OAAO,CAAC,IAAI,CAAC,gBAAgB,GAAG,EAAE,EAAE,GAAG,IAAI,CAAC,CAAA;IAC1E,CAAC;IAED,KAAK,CAAC,GAAW,EAAE,GAAG,IAAe;QACjC,IAAI,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC;YAAE,OAAO,CAAC,KAAK,CAAC,gBAAgB,GAAG,EAAE,EAAE,GAAG,IAAI,CAAC,CAAA;IAC5E,CAAC;IAED,OAAO,CAAC,GAAW,EAAE,GAAG,IAAe;QACnC,IAAI,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC;YAAE,OAAO,CAAC,KAAK,CAAC,gBAAgB,GAAG,EAAE,EAAE,GAAG,IAAI,CAAC,CAAA;IAC9E,CAAC;CACJ;AAED,MAAM,CAAC,MAAM,MAAM,GAAG,IAAI,UAAU,EAAE,CAAA;AAEtC,iFAAiF;AACjF,MAAM,UAAU,WAAW,CAAC,KAAe;IACvC,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAA;AAC1B,CAAC"}
@@ -0,0 +1,20 @@
1
+ export declare function stripNsPrefix(tag: string): string;
2
+ export declare function getMatchesForRegex(text: string, regex: RegExp): string[];
3
+ /** Returns the local name of the document's root element (strips namespace prefix). */
4
+ export declare function getRootTag(xmlText: string): string | undefined;
5
+ /**
6
+ * Returns the stack of tag names that are opened but not yet closed in `text`.
7
+ * Namespace prefixes are preserved — strip them with stripNsPrefix if needed.
8
+ *
9
+ * NOTE: attribute values must not contain literal `>` (use `>` instead).
10
+ * This is required by the XML spec and assumed here for regex-based matching.
11
+ */
12
+ export declare function getUnclosedTags(text: string): string[];
13
+ /** Returns the attribute names already present in the current opening tag. */
14
+ export declare function extractUsedAttributes(textUntilCursor: string): string[];
15
+ /**
16
+ * Returns the name of the attribute whose value the cursor is currently inside,
17
+ * or null if the cursor is not inside an attribute value.
18
+ */
19
+ export declare function extractCurrentAttributeName(textUntilCursor: string): string | null;
20
+ //# sourceMappingURL=XmlTextUtils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"XmlTextUtils.d.ts","sourceRoot":"","sources":["../../src/utils/XmlTextUtils.ts"],"names":[],"mappings":"AAAA,wBAAgB,aAAa,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAGjD;AAED,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,EAAE,CAWxE;AAED,uFAAuF;AACvF,wBAAgB,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAM9D;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CA4BtD;AAED,8EAA8E;AAC9E,wBAAgB,qBAAqB,CAAC,eAAe,EAAE,MAAM,GAAG,MAAM,EAAE,CAWvE;AAED;;;GAGG;AACH,wBAAgB,2BAA2B,CAAC,eAAe,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAQlF"}
@@ -0,0 +1,85 @@
1
+ export function stripNsPrefix(tag) {
2
+ const colon = tag.indexOf(':');
3
+ return colon >= 0 ? tag.slice(colon + 1) : tag;
4
+ }
5
+ export function getMatchesForRegex(text, regex) {
6
+ const global = new RegExp(regex.source, regex.flags.includes('g') ? regex.flags : regex.flags + 'g');
7
+ const results = [];
8
+ let match;
9
+ while ((match = global.exec(text)) !== null) {
10
+ results.push(match[0]);
11
+ }
12
+ return results;
13
+ }
14
+ /** Returns the local name of the document's root element (strips namespace prefix). */
15
+ export function getRootTag(xmlText) {
16
+ const cleaned = xmlText
17
+ .replace(/<\?[\s\S]*?\?>/g, '')
18
+ .replace(/<!--[\s\S]*?-->/g, '');
19
+ const match = /<([a-zA-Z_][\w:.-]*)[\s\/>]/.exec(cleaned);
20
+ return match ? stripNsPrefix(match[1]) : undefined;
21
+ }
22
+ /**
23
+ * Returns the stack of tag names that are opened but not yet closed in `text`.
24
+ * Namespace prefixes are preserved — strip them with stripNsPrefix if needed.
25
+ *
26
+ * NOTE: attribute values must not contain literal `>` (use `&gt;` instead).
27
+ * This is required by the XML spec and assumed here for regex-based matching.
28
+ */
29
+ export function getUnclosedTags(text) {
30
+ const cleaned = text
31
+ .replace(/<!--[\s\S]*?-->/g, '')
32
+ .replace(/<\?[\s\S]*?\?>/g, '')
33
+ .replace(/<!\[CDATA\[[\s\S]*?\]\]>/g, '')
34
+ .replace(/<!DOCTYPE[^>]*>/gi, '');
35
+ // Groups: [1] '/' for closing | '' for opening [2] tag name [3] '/>' for self-close
36
+ // The attributes section uses (?:[^>\/]|\/(?!>))* so that the '/' in '/>'
37
+ // is never consumed by the greedy attributes match and always lands in group 3.
38
+ const tagRe = /<(\/?)([a-zA-Z_][\w:.-]*)(?:\s(?:[^>\/]|\/(?!>))*)?(\/?)>/g;
39
+ const stack = [];
40
+ let match;
41
+ while ((match = tagRe.exec(cleaned)) !== null) {
42
+ const isClosing = match[1] === '/';
43
+ const name = match[2];
44
+ const isSelfClosing = match[3] === '/';
45
+ if (isClosing) {
46
+ const idx = stack.lastIndexOf(name);
47
+ if (idx >= 0)
48
+ stack.splice(idx, 1);
49
+ }
50
+ else if (!isSelfClosing) {
51
+ stack.push(name);
52
+ }
53
+ }
54
+ return stack;
55
+ }
56
+ /** Returns the attribute names already present in the current opening tag. */
57
+ export function extractUsedAttributes(textUntilCursor) {
58
+ const lastOpen = textUntilCursor.lastIndexOf('<');
59
+ if (lastOpen < 0)
60
+ return [];
61
+ const inTag = textUntilCursor.slice(lastOpen);
62
+ const attrRe = /\s([a-zA-Z_][\w:.-]*)=/g;
63
+ const used = [];
64
+ let match;
65
+ while ((match = attrRe.exec(inTag)) !== null) {
66
+ used.push(match[1]);
67
+ }
68
+ return used;
69
+ }
70
+ /**
71
+ * Returns the name of the attribute whose value the cursor is currently inside,
72
+ * or null if the cursor is not inside an attribute value.
73
+ */
74
+ export function extractCurrentAttributeName(textUntilCursor) {
75
+ const lastOpen = textUntilCursor.lastIndexOf('<');
76
+ if (lastOpen < 0)
77
+ return null;
78
+ const inTag = textUntilCursor.slice(lastOpen);
79
+ const dq = /\s([a-zA-Z_][\w:.-]*)="[^"]*$/.exec(inTag);
80
+ const sq = /\s([a-zA-Z_][\w:.-]*)='[^']*$/.exec(inTag);
81
+ if (dq && sq)
82
+ return dq.index > sq.index ? dq[1] : sq[1];
83
+ return dq?.[1] ?? sq?.[1] ?? null;
84
+ }
85
+ //# sourceMappingURL=XmlTextUtils.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"XmlTextUtils.js","sourceRoot":"","sources":["../../src/utils/XmlTextUtils.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,15 @@
1
+ import type { editor } from 'monaco-editor';
2
+ import type { IMonacoApi } from '../interfaces/IMonacoApi';
3
+ import { type ValidationError } from '../types';
4
+ /**
5
+ * Maps ValidationError[] → Monaco IModelDeltaDecoration[].
6
+ * Receives IMonacoApi at construction — never touches window.monaco.
7
+ */
8
+ export declare class DecorationMapper {
9
+ private readonly monacoApi;
10
+ constructor(monacoApi: IMonacoApi);
11
+ toDecorations(errors: ValidationError[], model: editor.ITextModel): editor.IModelDeltaDecoration[];
12
+ private cssClass;
13
+ private overviewColor;
14
+ }
15
+ //# sourceMappingURL=DecorationMapper.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DecorationMapper.d.ts","sourceRoot":"","sources":["../../src/validation/DecorationMapper.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAA;AAC3C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAA;AAC1D,OAAO,EAAY,KAAK,eAAe,EAAE,MAAM,UAAU,CAAA;AAEzD;;;GAGG;AACH,qBAAa,gBAAgB;IACb,OAAO,CAAC,QAAQ,CAAC,SAAS;gBAAT,SAAS,EAAE,UAAU;IAElD,aAAa,CACT,MAAM,EAAE,eAAe,EAAE,EACzB,KAAK,EAAE,MAAM,CAAC,UAAU,GACzB,MAAM,CAAC,qBAAqB,EAAE;IAoCjC,OAAO,CAAC,QAAQ;IAWhB,OAAO,CAAC,aAAa;CAUxB"}
@@ -0,0 +1,59 @@
1
+ import { Severity } from '../types';
2
+ /**
3
+ * Maps ValidationError[] → Monaco IModelDeltaDecoration[].
4
+ * Receives IMonacoApi at construction — never touches window.monaco.
5
+ */
6
+ export class DecorationMapper {
7
+ monacoApi;
8
+ constructor(monacoApi) {
9
+ this.monacoApi = monacoApi;
10
+ }
11
+ toDecorations(errors, model) {
12
+ return errors.map(error => {
13
+ const lineCount = model.getLineCount();
14
+ const safeLine = Math.max(1, Math.min(error.line, lineCount));
15
+ const endColumn = model.getLineMaxColumn(safeLine);
16
+ const startColumn = Math.max(1, error.col);
17
+ const range = new this.monacoApi.Range(safeLine, startColumn, safeLine, endColumn);
18
+ const className = this.cssClass(error.severity);
19
+ const hoverMessage = { value: error.message };
20
+ return {
21
+ range,
22
+ options: {
23
+ isWholeLine: false,
24
+ className,
25
+ hoverMessage,
26
+ overviewRuler: {
27
+ color: this.overviewColor(error.severity),
28
+ position: 4 /* OverviewRulerLane.Right */,
29
+ },
30
+ minimap: {
31
+ color: this.overviewColor(error.severity),
32
+ position: 1 /* MinimapPosition.Inline */,
33
+ },
34
+ },
35
+ };
36
+ });
37
+ }
38
+ cssClass(severity) {
39
+ switch (severity) {
40
+ case Severity.warning:
41
+ return 'mxls-warning-decoration';
42
+ case Severity.fatalError:
43
+ return 'mxls-fatal-decoration';
44
+ default:
45
+ return 'mxls-error-decoration';
46
+ }
47
+ }
48
+ overviewColor(severity) {
49
+ switch (severity) {
50
+ case Severity.warning:
51
+ return 'rgba(255, 200, 0, 0.8)';
52
+ case Severity.fatalError:
53
+ return 'rgba(200, 0, 0, 0.9)';
54
+ default:
55
+ return 'rgba(255, 50, 50, 0.8)';
56
+ }
57
+ }
58
+ }
59
+ //# sourceMappingURL=DecorationMapper.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"DecorationMapper.js","sourceRoot":"","sources":["../../src/validation/DecorationMapper.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,QAAQ,EAAwB,MAAM,UAAU,CAAA;AAEzD;;;GAGG;AACH,MAAM,OAAO,gBAAgB;IACI;IAA7B,YAA6B,SAAqB;QAArB,cAAS,GAAT,SAAS,CAAY;IAAG,CAAC;IAEtD,aAAa,CACT,MAAyB,EACzB,KAAwB;QAExB,OAAO,MAAM,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE;YACtB,MAAM,SAAS,GAAG,KAAK,CAAC,YAAY,EAAE,CAAA;YACtC,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,EAAE,SAAS,CAAC,CAAC,CAAA;YAC7D,MAAM,SAAS,GAAG,KAAK,CAAC,gBAAgB,CAAC,QAAQ,CAAC,CAAA;YAClD,MAAM,WAAW,GAAG,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,GAAG,CAAC,CAAA;YAE1C,MAAM,KAAK,GAAG,IAAI,IAAI,CAAC,SAAS,CAAC,KAAK,CAClC,QAAQ,EACR,WAAW,EACX,QAAQ,EACR,SAAS,CACZ,CAAA;YAED,MAAM,SAAS,GAAG,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAA;YAC/C,MAAM,YAAY,GAAG,EAAE,KAAK,EAAE,KAAK,CAAC,OAAO,EAAE,CAAA;YAE7C,OAAO;gBACH,KAAK;gBACL,OAAO,EAAE;oBACL,WAAW,EAAE,KAAK;oBAClB,SAAS;oBACT,YAAY;oBACZ,aAAa,EAAE;wBACX,KAAK,EAAE,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,QAAQ,CAAC;wBACzC,QAAQ,EAAE,CAAC,CAAC,6BAA6B;qBAC5C;oBACD,OAAO,EAAE;wBACL,KAAK,EAAE,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,QAAQ,CAAC;wBACzC,QAAQ,EAAE,CAAC,CAAC,4BAA4B;qBAC3C;iBACJ;aACmC,CAAA;QAC5C,CAAC,CAAC,CAAA;IACN,CAAC;IAEO,QAAQ,CAAC,QAAkB;QAC/B,QAAQ,QAAQ,EAAE,CAAC;YACf,KAAK,QAAQ,CAAC,OAAO;gBACjB,OAAO,yBAAyB,CAAA;YACpC,KAAK,QAAQ,CAAC,UAAU;gBACpB,OAAO,uBAAuB,CAAA;YAClC;gBACI,OAAO,uBAAuB,CAAA;QACtC,CAAC;IACL,CAAC;IAEO,aAAa,CAAC,QAAkB;QACpC,QAAQ,QAAQ,EAAE,CAAC;YACf,KAAK,QAAQ,CAAC,OAAO;gBACjB,OAAO,wBAAwB,CAAA;YACnC,KAAK,QAAQ,CAAC,UAAU;gBACpB,OAAO,sBAAsB,CAAA;YACjC;gBACI,OAAO,wBAAwB,CAAA;QACvC,CAAC;IACL,CAAC;CACJ"}
@@ -0,0 +1,26 @@
1
+ import type { editor } from 'monaco-editor';
2
+ import type { IMonacoApi } from '../interfaces/IMonacoApi';
3
+ import type { ISchemaWorker } from '../interfaces/ISchemaWorker';
4
+ /**
5
+ * Thin Monaco integration shell for XML validation.
6
+ * Wires model-change events → SchemaValidator → DecorationMapper → decorations.
7
+ * All validation logic lives in SchemaValidator (no Monaco dependency there).
8
+ */
9
+ export declare class SchemaDecorator {
10
+ private readonly codeEditor;
11
+ private readonly validator;
12
+ private readonly mapper;
13
+ private decorations;
14
+ private readonly disposeListener;
15
+ private getWorkers;
16
+ constructor(monacoApi: IMonacoApi, codeEditor: editor.IStandaloneCodeEditor);
17
+ /**
18
+ * Attach a worker provider and trigger an immediate validation run.
19
+ * Call this after the schema registry is ready.
20
+ */
21
+ revalidate(getWorkers: () => ISchemaWorker[]): void;
22
+ /** Remove the change listener and clear all decorations. */
23
+ dispose(): void;
24
+ private run;
25
+ }
26
+ //# sourceMappingURL=SchemaDecorator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SchemaDecorator.d.ts","sourceRoot":"","sources":["../../src/validation/SchemaDecorator.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,eAAe,CAAA;AAE3C,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,0BAA0B,CAAA;AAC1D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAA;AAIhE;;;;GAIG;AACH,qBAAa,eAAe;IASpB,OAAO,CAAC,QAAQ,CAAC,UAAU;IAR/B,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAwB;IAClD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAkB;IACzC,OAAO,CAAC,WAAW,CAAqC;IACxD,OAAO,CAAC,QAAQ,CAAC,eAAe,CAAqB;IACrD,OAAO,CAAC,UAAU,CAAuC;gBAGrD,SAAS,EAAE,UAAU,EACJ,UAAU,EAAE,MAAM,CAAC,qBAAqB;IAY7D;;;OAGG;IACH,UAAU,CAAC,UAAU,EAAE,MAAM,aAAa,EAAE,GAAG,IAAI;IAKnD,4DAA4D;IAC5D,OAAO,IAAI,IAAI;IAKf,OAAO,CAAC,GAAG;CAWd"}
@@ -0,0 +1,50 @@
1
+ import { debounce } from 'ts-debounce';
2
+ import { SchemaValidator } from './SchemaValidator';
3
+ import { DecorationMapper } from './DecorationMapper';
4
+ /**
5
+ * Thin Monaco integration shell for XML validation.
6
+ * Wires model-change events → SchemaValidator → DecorationMapper → decorations.
7
+ * All validation logic lives in SchemaValidator (no Monaco dependency there).
8
+ */
9
+ export class SchemaDecorator {
10
+ codeEditor;
11
+ validator = new SchemaValidator();
12
+ mapper;
13
+ decorations;
14
+ disposeListener;
15
+ getWorkers = null;
16
+ constructor(monacoApi, codeEditor) {
17
+ this.codeEditor = codeEditor;
18
+ this.mapper = new DecorationMapper(monacoApi);
19
+ this.decorations = codeEditor.createDecorationsCollection([]);
20
+ const debouncedRun = debounce(() => this.run(), 500);
21
+ this.disposeListener = codeEditor.onDidChangeModelContent(() => {
22
+ if (this.getWorkers)
23
+ debouncedRun();
24
+ });
25
+ }
26
+ /**
27
+ * Attach a worker provider and trigger an immediate validation run.
28
+ * Call this after the schema registry is ready.
29
+ */
30
+ revalidate(getWorkers) {
31
+ this.getWorkers = getWorkers;
32
+ this.run();
33
+ }
34
+ /** Remove the change listener and clear all decorations. */
35
+ dispose() {
36
+ this.disposeListener.dispose();
37
+ this.decorations.clear();
38
+ }
39
+ run() {
40
+ const model = this.codeEditor.getModel();
41
+ if (!model || !this.getWorkers)
42
+ return;
43
+ const xml = model.getValue();
44
+ const workers = this.getWorkers();
45
+ const errors = this.validator.validate(xml, workers);
46
+ const newDecorations = this.mapper.toDecorations(errors, model);
47
+ this.decorations.set(newDecorations);
48
+ }
49
+ }
50
+ //# sourceMappingURL=SchemaDecorator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SchemaDecorator.js","sourceRoot":"","sources":["../../src/validation/SchemaDecorator.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAA;AAGtC,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAA;AACnD,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAA;AAErD;;;;GAIG;AACH,MAAM,OAAO,eAAe;IASH;IARJ,SAAS,GAAG,IAAI,eAAe,EAAE,CAAA;IACjC,MAAM,CAAkB;IACjC,WAAW,CAAqC;IACvC,eAAe,CAAqB;IAC7C,UAAU,GAAmC,IAAI,CAAA;IAEzD,YACI,SAAqB,EACJ,UAAwC;QAAxC,eAAU,GAAV,UAAU,CAA8B;QAEzD,IAAI,CAAC,MAAM,GAAG,IAAI,gBAAgB,CAAC,SAAS,CAAC,CAAA;QAC7C,IAAI,CAAC,WAAW,GAAG,UAAU,CAAC,2BAA2B,CAAC,EAAE,CAAC,CAAA;QAE7D,MAAM,YAAY,GAAG,QAAQ,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,GAAG,EAAE,EAAE,GAAG,CAAC,CAAA;QAEpD,IAAI,CAAC,eAAe,GAAG,UAAU,CAAC,uBAAuB,CAAC,GAAG,EAAE;YAC3D,IAAI,IAAI,CAAC,UAAU;gBAAE,YAAY,EAAE,CAAA;QACvC,CAAC,CAAC,CAAA;IACN,CAAC;IAED;;;OAGG;IACH,UAAU,CAAC,UAAiC;QACxC,IAAI,CAAC,UAAU,GAAG,UAAU,CAAA;QAC5B,IAAI,CAAC,GAAG,EAAE,CAAA;IACd,CAAC;IAED,4DAA4D;IAC5D,OAAO;QACH,IAAI,CAAC,eAAe,CAAC,OAAO,EAAE,CAAA;QAC9B,IAAI,CAAC,WAAW,CAAC,KAAK,EAAE,CAAA;IAC5B,CAAC;IAEO,GAAG;QACP,MAAM,KAAK,GAAG,IAAI,CAAC,UAAU,CAAC,QAAQ,EAAE,CAAA;QACxC,IAAI,CAAC,KAAK,IAAI,CAAC,IAAI,CAAC,UAAU;YAAE,OAAM;QAEtC,MAAM,GAAG,GAAG,KAAK,CAAC,QAAQ,EAAE,CAAA;QAC5B,MAAM,OAAO,GAAG,IAAI,CAAC,UAAU,EAAE,CAAA;QACjC,MAAM,MAAM,GAAG,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,GAAG,EAAE,OAAO,CAAC,CAAA;QACpD,MAAM,cAAc,GAAG,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,MAAM,EAAE,KAAK,CAAC,CAAA;QAE/D,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,cAAc,CAAC,CAAA;IACxC,CAAC;CACJ"}
@@ -0,0 +1,13 @@
1
+ import type { ISchemaWorker } from '../interfaces/ISchemaWorker';
2
+ import { type ValidationError } from '../types';
3
+ /**
4
+ * Pure validator: no Monaco dependency, fully testable in Node.
5
+ * Returns a deduplicated array of ValidationError for the given XML string
6
+ * checked against all provided schema workers.
7
+ */
8
+ export declare class SchemaValidator {
9
+ validate(xml: string, workers: ISchemaWorker[]): ValidationError[];
10
+ private checkDuplicateAttributes;
11
+ private deduplicate;
12
+ }
13
+ //# sourceMappingURL=SchemaValidator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SchemaValidator.d.ts","sourceRoot":"","sources":["../../src/validation/SchemaValidator.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,6BAA6B,CAAA;AAChE,OAAO,EAA8B,KAAK,eAAe,EAAE,MAAM,UAAU,CAAA;AAyF3E;;;;GAIG;AACH,qBAAa,eAAe;IACxB,QAAQ,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,aAAa,EAAE,GAAG,eAAe,EAAE;IA2QlE,OAAO,CAAC,wBAAwB;IAqDhC,OAAO,CAAC,WAAW;CAStB"}