@coherent.js/language-server 1.0.0-beta.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.
Files changed (43) hide show
  1. package/LICENSE +21 -0
  2. package/dist/analysis/coherent-analyzer.d.ts +93 -0
  3. package/dist/analysis/coherent-analyzer.d.ts.map +1 -0
  4. package/dist/analysis/coherent-analyzer.js +288 -0
  5. package/dist/analysis/coherent-analyzer.js.map +1 -0
  6. package/dist/analysis/element-validator.d.ts +45 -0
  7. package/dist/analysis/element-validator.d.ts.map +1 -0
  8. package/dist/analysis/element-validator.js +84 -0
  9. package/dist/analysis/element-validator.js.map +1 -0
  10. package/dist/analysis/nesting-validator.d.ts +49 -0
  11. package/dist/analysis/nesting-validator.d.ts.map +1 -0
  12. package/dist/analysis/nesting-validator.js +68 -0
  13. package/dist/analysis/nesting-validator.js.map +1 -0
  14. package/dist/data/element-attributes.d.ts +92 -0
  15. package/dist/data/element-attributes.d.ts.map +1 -0
  16. package/dist/data/element-attributes.generated.json +7085 -0
  17. package/dist/data/element-attributes.js +282 -0
  18. package/dist/data/element-attributes.js.map +1 -0
  19. package/dist/data/nesting-rules.d.ts +67 -0
  20. package/dist/data/nesting-rules.d.ts.map +1 -0
  21. package/dist/data/nesting-rules.js +240 -0
  22. package/dist/data/nesting-rules.js.map +1 -0
  23. package/dist/providers/code-actions.d.ts +15 -0
  24. package/dist/providers/code-actions.d.ts.map +1 -0
  25. package/dist/providers/code-actions.js +191 -0
  26. package/dist/providers/code-actions.js.map +1 -0
  27. package/dist/providers/completion.d.ts +15 -0
  28. package/dist/providers/completion.d.ts.map +1 -0
  29. package/dist/providers/completion.js +247 -0
  30. package/dist/providers/completion.js.map +1 -0
  31. package/dist/providers/diagnostics.d.ts +26 -0
  32. package/dist/providers/diagnostics.d.ts.map +1 -0
  33. package/dist/providers/diagnostics.js +143 -0
  34. package/dist/providers/diagnostics.js.map +1 -0
  35. package/dist/providers/hover.d.ts +15 -0
  36. package/dist/providers/hover.d.ts.map +1 -0
  37. package/dist/providers/hover.js +215 -0
  38. package/dist/providers/hover.js.map +1 -0
  39. package/dist/server.d.ts +17 -0
  40. package/dist/server.d.ts.map +1 -0
  41. package/dist/server.js +82 -0
  42. package/dist/server.js.map +1 -0
  43. package/package.json +53 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Thomas Drouvin
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,93 @@
1
+ /**
2
+ * Coherent.js Object Analyzer
3
+ *
4
+ * Uses TypeScript AST to detect and analyze Coherent.js element objects
5
+ * in source code. Identifies tag names, attributes, children, and nesting.
6
+ */
7
+ import * as ts from 'typescript';
8
+ import { Range, Position } from 'vscode-languageserver';
9
+ /**
10
+ * Information about a detected Coherent.js element.
11
+ */
12
+ export interface CoherentElementInfo {
13
+ /** HTML tag name (e.g., 'div', 'input') */
14
+ tagName: string;
15
+ /** Source code range of the entire element object */
16
+ range: Range;
17
+ /** Source code range of just the tag name property */
18
+ tagNameRange: Range;
19
+ /** Attributes found on this element */
20
+ attributes: AttributeInfo[];
21
+ /** Parent element info (if nested) */
22
+ parent: CoherentElementInfo | null;
23
+ /** Children elements */
24
+ children: CoherentElementInfo[];
25
+ /** The TypeScript AST node */
26
+ node: ts.ObjectLiteralExpression;
27
+ }
28
+ /**
29
+ * Information about an attribute on a Coherent element.
30
+ */
31
+ export interface AttributeInfo {
32
+ /** Attribute name (e.g., 'className', 'onClick') */
33
+ name: string;
34
+ /** Attribute value as string (for display) */
35
+ value: string;
36
+ /** Source code range of the attribute */
37
+ range: Range;
38
+ /** Source code range of just the attribute name */
39
+ nameRange: Range;
40
+ /** The TypeScript AST node */
41
+ node: ts.PropertyAssignment | ts.ShorthandPropertyAssignment;
42
+ }
43
+ /**
44
+ * Context for position-based queries.
45
+ */
46
+ export interface PositionContext {
47
+ /** Type of context at the position */
48
+ type: 'tag-name' | 'attribute-name' | 'attribute-value' | 'children' | 'outside';
49
+ /** Current element (if inside one) */
50
+ element?: CoherentElementInfo;
51
+ /** Current attribute (if inside one) */
52
+ attribute?: AttributeInfo;
53
+ }
54
+ /**
55
+ * Check if a node is a Coherent.js element object.
56
+ *
57
+ * A Coherent element is an object with a single property whose name is an HTML tag,
58
+ * and whose value is an object containing attributes.
59
+ */
60
+ export declare function isCoherentElement(node: ts.Node, sourceFile: ts.SourceFile): node is ts.ObjectLiteralExpression;
61
+ /**
62
+ * Find all Coherent.js elements in a source file.
63
+ *
64
+ * @param sourceFile - TypeScript source file to analyze
65
+ * @returns Array of found Coherent element info
66
+ */
67
+ export declare function findCoherentElements(sourceFile: ts.SourceFile): CoherentElementInfo[];
68
+ /**
69
+ * Get the Coherent element at a specific position.
70
+ *
71
+ * @param sourceFile - TypeScript source file
72
+ * @param position - LSP position
73
+ * @param elements - Previously found elements (optional, will find if not provided)
74
+ * @returns Element info at position or undefined
75
+ */
76
+ export declare function getElementAtPosition(sourceFile: ts.SourceFile, position: Position, elements?: CoherentElementInfo[]): CoherentElementInfo | undefined;
77
+ /**
78
+ * Get the context at a specific position for completion/hover.
79
+ *
80
+ * @param sourceFile - TypeScript source file
81
+ * @param position - LSP position
82
+ * @returns Context information
83
+ */
84
+ export declare function getPositionContext(sourceFile: ts.SourceFile, position: Position): PositionContext;
85
+ /**
86
+ * Create a TypeScript source file from text content.
87
+ *
88
+ * @param content - Source file content
89
+ * @param fileName - File name for the source file
90
+ * @returns TypeScript SourceFile
91
+ */
92
+ export declare function createSourceFile(content: string, fileName: string): ts.SourceFile;
93
+ //# sourceMappingURL=coherent-analyzer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"coherent-analyzer.d.ts","sourceRoot":"","sources":["../../src/analysis/coherent-analyzer.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,KAAK,EAAE,MAAM,YAAY,CAAC;AAEjC,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,MAAM,uBAAuB,CAAC;AAExD;;GAEG;AACH,MAAM,WAAW,mBAAmB;IAClC,2CAA2C;IAC3C,OAAO,EAAE,MAAM,CAAC;IAEhB,qDAAqD;IACrD,KAAK,EAAE,KAAK,CAAC;IAEb,sDAAsD;IACtD,YAAY,EAAE,KAAK,CAAC;IAEpB,uCAAuC;IACvC,UAAU,EAAE,aAAa,EAAE,CAAC;IAE5B,sCAAsC;IACtC,MAAM,EAAE,mBAAmB,GAAG,IAAI,CAAC;IAEnC,wBAAwB;IACxB,QAAQ,EAAE,mBAAmB,EAAE,CAAC;IAEhC,8BAA8B;IAC9B,IAAI,EAAE,EAAE,CAAC,uBAAuB,CAAC;CAClC;AAED;;GAEG;AACH,MAAM,WAAW,aAAa;IAC5B,oDAAoD;IACpD,IAAI,EAAE,MAAM,CAAC;IAEb,8CAA8C;IAC9C,KAAK,EAAE,MAAM,CAAC;IAEd,yCAAyC;IACzC,KAAK,EAAE,KAAK,CAAC;IAEb,mDAAmD;IACnD,SAAS,EAAE,KAAK,CAAC;IAEjB,8BAA8B;IAC9B,IAAI,EAAE,EAAE,CAAC,kBAAkB,GAAG,EAAE,CAAC,2BAA2B,CAAC;CAC9D;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,sCAAsC;IACtC,IAAI,EAAE,UAAU,GAAG,gBAAgB,GAAG,iBAAiB,GAAG,UAAU,GAAG,SAAS,CAAC;IAEjF,sCAAsC;IACtC,OAAO,CAAC,EAAE,mBAAmB,CAAC;IAE9B,wCAAwC;IACxC,SAAS,CAAC,EAAE,aAAa,CAAC;CAC3B;AA8CD;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,EAAE,UAAU,EAAE,EAAE,CAAC,UAAU,GAAG,IAAI,IAAI,EAAE,CAAC,uBAAuB,CA4B9G;AAmGD;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAAC,UAAU,EAAE,EAAE,CAAC,UAAU,GAAG,mBAAmB,EAAE,CAyBrF;AAED;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAClC,UAAU,EAAE,EAAE,CAAC,UAAU,EACzB,QAAQ,EAAE,QAAQ,EAClB,QAAQ,CAAC,EAAE,mBAAmB,EAAE,GAC/B,mBAAmB,GAAG,SAAS,CAgBjC;AAcD;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAChC,UAAU,EAAE,EAAE,CAAC,UAAU,EACzB,QAAQ,EAAE,QAAQ,GACjB,eAAe,CA+CjB;AAED;;;;;;GAMG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,EAAE,CAAC,UAAU,CAQjF"}
@@ -0,0 +1,288 @@
1
+ /**
2
+ * Coherent.js Object Analyzer
3
+ *
4
+ * Uses TypeScript AST to detect and analyze Coherent.js element objects
5
+ * in source code. Identifies tag names, attributes, children, and nesting.
6
+ */
7
+ import * as ts from 'typescript';
8
+ import { HTML_ELEMENTS } from '../data/element-attributes.js';
9
+ /**
10
+ * Convert TypeScript position to LSP position.
11
+ */
12
+ function tsPositionToLsp(sourceFile, pos) {
13
+ const lineAndChar = sourceFile.getLineAndCharacterOfPosition(pos);
14
+ return {
15
+ line: lineAndChar.line,
16
+ character: lineAndChar.character,
17
+ };
18
+ }
19
+ /**
20
+ * Convert TypeScript range to LSP range.
21
+ */
22
+ function tsRangeToLsp(sourceFile, start, end) {
23
+ return {
24
+ start: tsPositionToLsp(sourceFile, start),
25
+ end: tsPositionToLsp(sourceFile, end),
26
+ };
27
+ }
28
+ /**
29
+ * Convert LSP position to TypeScript offset.
30
+ */
31
+ function lspPositionToTs(sourceFile, position) {
32
+ return sourceFile.getPositionOfLineAndCharacter(position.line, position.character);
33
+ }
34
+ /**
35
+ * Check if a position is within a range.
36
+ */
37
+ function isPositionInRange(position, range) {
38
+ if (position.line < range.start.line || position.line > range.end.line) {
39
+ return false;
40
+ }
41
+ if (position.line === range.start.line && position.character < range.start.character) {
42
+ return false;
43
+ }
44
+ if (position.line === range.end.line && position.character > range.end.character) {
45
+ return false;
46
+ }
47
+ return true;
48
+ }
49
+ /**
50
+ * Check if a node is a Coherent.js element object.
51
+ *
52
+ * A Coherent element is an object with a single property whose name is an HTML tag,
53
+ * and whose value is an object containing attributes.
54
+ */
55
+ export function isCoherentElement(node, sourceFile) {
56
+ if (!ts.isObjectLiteralExpression(node)) {
57
+ return false;
58
+ }
59
+ // Must have exactly one property
60
+ if (node.properties.length !== 1) {
61
+ return false;
62
+ }
63
+ const prop = node.properties[0];
64
+ if (!ts.isPropertyAssignment(prop)) {
65
+ return false;
66
+ }
67
+ // Property name must be an HTML element
68
+ const name = prop.name;
69
+ let tagName;
70
+ if (ts.isIdentifier(name)) {
71
+ tagName = name.text;
72
+ }
73
+ else if (ts.isStringLiteral(name)) {
74
+ tagName = name.text;
75
+ }
76
+ else {
77
+ return false;
78
+ }
79
+ return HTML_ELEMENTS.has(tagName);
80
+ }
81
+ /**
82
+ * Extract element information from a Coherent element node.
83
+ */
84
+ function extractElementInfo(node, sourceFile, parent = null) {
85
+ const prop = node.properties[0];
86
+ const name = prop.name;
87
+ let tagName;
88
+ if (ts.isIdentifier(name)) {
89
+ tagName = name.text;
90
+ }
91
+ else if (ts.isStringLiteral(name)) {
92
+ tagName = name.text;
93
+ }
94
+ else {
95
+ tagName = 'unknown';
96
+ }
97
+ const elementInfo = {
98
+ tagName,
99
+ range: tsRangeToLsp(sourceFile, node.getStart(sourceFile), node.getEnd()),
100
+ tagNameRange: tsRangeToLsp(sourceFile, name.getStart(sourceFile), name.getEnd()),
101
+ attributes: [],
102
+ parent,
103
+ children: [],
104
+ node,
105
+ };
106
+ // Extract attributes from the property value
107
+ if (ts.isObjectLiteralExpression(prop.initializer)) {
108
+ const attrs = prop.initializer;
109
+ for (const attrProp of attrs.properties) {
110
+ if (ts.isPropertyAssignment(attrProp)) {
111
+ const attrName = ts.isIdentifier(attrProp.name)
112
+ ? attrProp.name.text
113
+ : ts.isStringLiteral(attrProp.name)
114
+ ? attrProp.name.text
115
+ : null;
116
+ if (attrName) {
117
+ const attrInfo = {
118
+ name: attrName,
119
+ value: attrProp.initializer.getText(sourceFile),
120
+ range: tsRangeToLsp(sourceFile, attrProp.getStart(sourceFile), attrProp.getEnd()),
121
+ nameRange: tsRangeToLsp(sourceFile, attrProp.name.getStart(sourceFile), attrProp.name.getEnd()),
122
+ node: attrProp,
123
+ };
124
+ elementInfo.attributes.push(attrInfo);
125
+ // Check for children array and extract nested elements
126
+ if (attrName === 'children') {
127
+ extractChildElements(attrProp.initializer, sourceFile, elementInfo);
128
+ }
129
+ }
130
+ }
131
+ else if (ts.isShorthandPropertyAssignment(attrProp)) {
132
+ const attrName = attrProp.name.text;
133
+ const attrInfo = {
134
+ name: attrName,
135
+ value: attrName, // Shorthand uses same name as value
136
+ range: tsRangeToLsp(sourceFile, attrProp.getStart(sourceFile), attrProp.getEnd()),
137
+ nameRange: tsRangeToLsp(sourceFile, attrProp.name.getStart(sourceFile), attrProp.name.getEnd()),
138
+ node: attrProp,
139
+ };
140
+ elementInfo.attributes.push(attrInfo);
141
+ }
142
+ }
143
+ }
144
+ return elementInfo;
145
+ }
146
+ /**
147
+ * Extract child Coherent elements from a children property value.
148
+ */
149
+ function extractChildElements(node, sourceFile, parent) {
150
+ if (ts.isArrayLiteralExpression(node)) {
151
+ // Children array
152
+ for (const element of node.elements) {
153
+ if (isCoherentElement(element, sourceFile)) {
154
+ const childInfo = extractElementInfo(element, sourceFile, parent);
155
+ parent.children.push(childInfo);
156
+ }
157
+ }
158
+ }
159
+ else if (isCoherentElement(node, sourceFile)) {
160
+ // Single child element
161
+ const childInfo = extractElementInfo(node, sourceFile, parent);
162
+ parent.children.push(childInfo);
163
+ }
164
+ }
165
+ /**
166
+ * Find all Coherent.js elements in a source file.
167
+ *
168
+ * @param sourceFile - TypeScript source file to analyze
169
+ * @returns Array of found Coherent element info
170
+ */
171
+ export function findCoherentElements(sourceFile) {
172
+ const elements = [];
173
+ const processed = new WeakSet();
174
+ function visit(node, parent = null) {
175
+ if (isCoherentElement(node, sourceFile) && !processed.has(node)) {
176
+ processed.add(node);
177
+ const elementInfo = extractElementInfo(node, sourceFile, parent);
178
+ elements.push(elementInfo);
179
+ // Also collect nested elements that were added as children
180
+ function collectChildren(el) {
181
+ for (const child of el.children) {
182
+ elements.push(child);
183
+ collectChildren(child);
184
+ }
185
+ }
186
+ collectChildren(elementInfo);
187
+ }
188
+ else {
189
+ ts.forEachChild(node, (child) => visit(child, parent));
190
+ }
191
+ }
192
+ visit(sourceFile);
193
+ return elements;
194
+ }
195
+ /**
196
+ * Get the Coherent element at a specific position.
197
+ *
198
+ * @param sourceFile - TypeScript source file
199
+ * @param position - LSP position
200
+ * @param elements - Previously found elements (optional, will find if not provided)
201
+ * @returns Element info at position or undefined
202
+ */
203
+ export function getElementAtPosition(sourceFile, position, elements) {
204
+ const allElements = elements || findCoherentElements(sourceFile);
205
+ // Find the most specific (deepest) element containing the position
206
+ let result;
207
+ for (const element of allElements) {
208
+ if (isPositionInRange(position, element.range)) {
209
+ // Prefer more specific (smaller range) element
210
+ if (!result || isRangeContained(element.range, result.range)) {
211
+ result = element;
212
+ }
213
+ }
214
+ }
215
+ return result;
216
+ }
217
+ /**
218
+ * Check if range a is contained within range b.
219
+ */
220
+ function isRangeContained(a, b) {
221
+ if (a.start.line > b.start.line || (a.start.line === b.start.line && a.start.character >= b.start.character)) {
222
+ if (a.end.line < b.end.line || (a.end.line === b.end.line && a.end.character <= b.end.character)) {
223
+ return true;
224
+ }
225
+ }
226
+ return false;
227
+ }
228
+ /**
229
+ * Get the context at a specific position for completion/hover.
230
+ *
231
+ * @param sourceFile - TypeScript source file
232
+ * @param position - LSP position
233
+ * @returns Context information
234
+ */
235
+ export function getPositionContext(sourceFile, position) {
236
+ const elements = findCoherentElements(sourceFile);
237
+ const element = getElementAtPosition(sourceFile, position, elements);
238
+ if (!element) {
239
+ return { type: 'outside' };
240
+ }
241
+ // Check if on tag name
242
+ if (isPositionInRange(position, element.tagNameRange)) {
243
+ return { type: 'tag-name', element };
244
+ }
245
+ // Check if on an attribute
246
+ for (const attr of element.attributes) {
247
+ if (isPositionInRange(position, attr.nameRange)) {
248
+ return { type: 'attribute-name', element, attribute: attr };
249
+ }
250
+ if (isPositionInRange(position, attr.range) && !isPositionInRange(position, attr.nameRange)) {
251
+ return { type: 'attribute-value', element, attribute: attr };
252
+ }
253
+ }
254
+ // Check if in children context (after children: [ or just after children:)
255
+ const offset = lspPositionToTs(sourceFile, position);
256
+ const text = sourceFile.text;
257
+ // Look backward from position to see context
258
+ let i = offset - 1;
259
+ while (i >= 0 && (text[i] === ' ' || text[i] === '\n' || text[i] === '\r' || text[i] === '\t')) {
260
+ i--;
261
+ }
262
+ if (i >= 0) {
263
+ // Check if we're right after [ or { in a children context
264
+ if (text[i] === '[' || text[i] === '{' || text[i] === ',') {
265
+ // Check if this is within a children attribute
266
+ const childrenAttr = element.attributes.find(a => a.name === 'children');
267
+ if (childrenAttr && isPositionInRange(position, childrenAttr.range)) {
268
+ return { type: 'children', element };
269
+ }
270
+ }
271
+ }
272
+ // Default to attribute-name context if inside element but not on specific attribute
273
+ // This allows completion of new attributes
274
+ return { type: 'attribute-name', element };
275
+ }
276
+ /**
277
+ * Create a TypeScript source file from text content.
278
+ *
279
+ * @param content - Source file content
280
+ * @param fileName - File name for the source file
281
+ * @returns TypeScript SourceFile
282
+ */
283
+ export function createSourceFile(content, fileName) {
284
+ return ts.createSourceFile(fileName, content, ts.ScriptTarget.Latest, true, // setParentNodes
285
+ ts.ScriptKind.TSX // Support both JS and TSX syntax
286
+ );
287
+ }
288
+ //# sourceMappingURL=coherent-analyzer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"coherent-analyzer.js","sourceRoot":"","sources":["../../src/analysis/coherent-analyzer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,45 @@
1
+ /**
2
+ * Element Attribute Validator
3
+ *
4
+ * Validates attributes on Coherent.js elements against the allowed
5
+ * attributes for each HTML element type.
6
+ */
7
+ import { Range } from 'vscode-languageserver';
8
+ import { CoherentElementInfo } from './coherent-analyzer.js';
9
+ /**
10
+ * Validation error for an attribute.
11
+ */
12
+ export interface AttributeValidationError {
13
+ /** Error message */
14
+ message: string;
15
+ /** Source range of the error */
16
+ range: Range;
17
+ /** Error code for categorization */
18
+ code: 'invalid-attribute' | 'typo-attribute' | 'void-children';
19
+ /** Severity of the error */
20
+ severity: 'error' | 'warning';
21
+ /** Suggestion for fix (for typos) */
22
+ suggestion?: string;
23
+ /** Additional data for code actions */
24
+ data?: Record<string, unknown>;
25
+ }
26
+ /**
27
+ * Validate attributes on a Coherent element.
28
+ *
29
+ * Checks for:
30
+ * - Invalid attribute names for the element
31
+ * - Typos in attribute names (with suggestions)
32
+ * - Children on void elements
33
+ *
34
+ * @param element - The Coherent element to validate
35
+ * @returns Array of validation errors
36
+ */
37
+ export declare function validateAttributes(element: CoherentElementInfo): AttributeValidationError[];
38
+ /**
39
+ * Validate multiple elements at once.
40
+ *
41
+ * @param elements - Array of Coherent elements to validate
42
+ * @returns Array of all validation errors
43
+ */
44
+ export declare function validateAllAttributes(elements: CoherentElementInfo[]): AttributeValidationError[];
45
+ //# sourceMappingURL=element-validator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"element-validator.d.ts","sourceRoot":"","sources":["../../src/analysis/element-validator.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAC9C,OAAO,EAAiB,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAO5E;;GAEG;AACH,MAAM,WAAW,wBAAwB;IACvC,oBAAoB;IACpB,OAAO,EAAE,MAAM,CAAC;IAEhB,gCAAgC;IAChC,KAAK,EAAE,KAAK,CAAC;IAEb,oCAAoC;IACpC,IAAI,EAAE,mBAAmB,GAAG,gBAAgB,GAAG,eAAe,CAAC;IAE/D,4BAA4B;IAC5B,QAAQ,EAAE,OAAO,GAAG,SAAS,CAAC;IAE9B,qCAAqC;IACrC,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB,uCAAuC;IACvC,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAChC;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,mBAAmB,GAAG,wBAAwB,EAAE,CAsD3F;AAED;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,mBAAmB,EAAE,GAAG,wBAAwB,EAAE,CAQjG"}
@@ -0,0 +1,84 @@
1
+ /**
2
+ * Element Attribute Validator
3
+ *
4
+ * Validates attributes on Coherent.js elements against the allowed
5
+ * attributes for each HTML element type.
6
+ */
7
+ import { isValidAttribute, isVoidElement, getSuggestions, } from '../data/element-attributes.js';
8
+ /**
9
+ * Validate attributes on a Coherent element.
10
+ *
11
+ * Checks for:
12
+ * - Invalid attribute names for the element
13
+ * - Typos in attribute names (with suggestions)
14
+ * - Children on void elements
15
+ *
16
+ * @param element - The Coherent element to validate
17
+ * @returns Array of validation errors
18
+ */
19
+ export function validateAttributes(element) {
20
+ const errors = [];
21
+ const tagName = element.tagName;
22
+ for (const attr of element.attributes) {
23
+ // Skip Coherent-specific properties that we handle separately
24
+ if (attr.name === 'children' || attr.name === 'text' || attr.name === 'html' || attr.name === 'key') {
25
+ // Check for children on void elements
26
+ if (attr.name === 'children' && isVoidElement(tagName)) {
27
+ errors.push({
28
+ message: `<${tagName}> is a void element and cannot have children`,
29
+ range: attr.range,
30
+ code: 'void-children',
31
+ severity: 'error',
32
+ data: { tagName, attributeName: attr.name },
33
+ });
34
+ }
35
+ continue;
36
+ }
37
+ // Check if attribute is valid for this element
38
+ if (!isValidAttribute(tagName, attr.name)) {
39
+ // Check for typo suggestions
40
+ const suggestions = getSuggestions(tagName, attr.name);
41
+ if (suggestions.length > 0) {
42
+ errors.push({
43
+ message: `Unknown attribute '${attr.name}' on <${tagName}>. Did you mean '${suggestions[0]}'?`,
44
+ range: attr.nameRange,
45
+ code: 'typo-attribute',
46
+ severity: 'error',
47
+ suggestion: suggestions[0],
48
+ data: {
49
+ tagName,
50
+ attributeName: attr.name,
51
+ suggestions,
52
+ },
53
+ });
54
+ }
55
+ else {
56
+ errors.push({
57
+ message: `Attribute '${attr.name}' is not valid for <${tagName}>`,
58
+ range: attr.nameRange,
59
+ code: 'invalid-attribute',
60
+ severity: 'error',
61
+ data: {
62
+ tagName,
63
+ attributeName: attr.name,
64
+ },
65
+ });
66
+ }
67
+ }
68
+ }
69
+ return errors;
70
+ }
71
+ /**
72
+ * Validate multiple elements at once.
73
+ *
74
+ * @param elements - Array of Coherent elements to validate
75
+ * @returns Array of all validation errors
76
+ */
77
+ export function validateAllAttributes(elements) {
78
+ const errors = [];
79
+ for (const element of elements) {
80
+ errors.push(...validateAttributes(element));
81
+ }
82
+ return errors;
83
+ }
84
+ //# sourceMappingURL=element-validator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"element-validator.js","sourceRoot":"","sources":["../../src/analysis/element-validator.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAIH,OAAO,EACL,gBAAgB,EAChB,aAAa,EACb,cAAc,GACf,MAAM,+BAA+B,CAAC;AAyBvC;;;;;;;;;;GAUG;AACH,MAAM,UAAU,kBAAkB,CAAC,OAA4B;IAC7D,MAAM,MAAM,GAA+B,EAAE,CAAC;IAC9C,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;IAEhC,KAAK,MAAM,IAAI,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC;QACtC,8DAA8D;QAC9D,IAAI,IAAI,CAAC,IAAI,KAAK,UAAU,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM,IAAI,IAAI,CAAC,IAAI,KAAK,KAAK,EAAE,CAAC;YACpG,sCAAsC;YACtC,IAAI,IAAI,CAAC,IAAI,KAAK,UAAU,IAAI,aAAa,CAAC,OAAO,CAAC,EAAE,CAAC;gBACvD,MAAM,CAAC,IAAI,CAAC;oBACV,OAAO,EAAE,IAAI,OAAO,8CAA8C;oBAClE,KAAK,EAAE,IAAI,CAAC,KAAK;oBACjB,IAAI,EAAE,eAAe;oBACrB,QAAQ,EAAE,OAAO;oBACjB,IAAI,EAAE,EAAE,OAAO,EAAE,aAAa,EAAE,IAAI,CAAC,IAAI,EAAE;iBAC5C,CAAC,CAAC;YACL,CAAC;YACD,SAAS;QACX,CAAC;QAED,+CAA+C;QAC/C,IAAI,CAAC,gBAAgB,CAAC,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;YAC1C,6BAA6B;YAC7B,MAAM,WAAW,GAAG,cAAc,CAAC,OAAO,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;YAEvD,IAAI,WAAW,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC3B,MAAM,CAAC,IAAI,CAAC;oBACV,OAAO,EAAE,sBAAsB,IAAI,CAAC,IAAI,SAAS,OAAO,oBAAoB,WAAW,CAAC,CAAC,CAAC,IAAI;oBAC9F,KAAK,EAAE,IAAI,CAAC,SAAS;oBACrB,IAAI,EAAE,gBAAgB;oBACtB,QAAQ,EAAE,OAAO;oBACjB,UAAU,EAAE,WAAW,CAAC,CAAC,CAAC;oBAC1B,IAAI,EAAE;wBACJ,OAAO;wBACP,aAAa,EAAE,IAAI,CAAC,IAAI;wBACxB,WAAW;qBACZ;iBACF,CAAC,CAAC;YACL,CAAC;iBAAM,CAAC;gBACN,MAAM,CAAC,IAAI,CAAC;oBACV,OAAO,EAAE,cAAc,IAAI,CAAC,IAAI,uBAAuB,OAAO,GAAG;oBACjE,KAAK,EAAE,IAAI,CAAC,SAAS;oBACrB,IAAI,EAAE,mBAAmB;oBACzB,QAAQ,EAAE,OAAO;oBACjB,IAAI,EAAE;wBACJ,OAAO;wBACP,aAAa,EAAE,IAAI,CAAC,IAAI;qBACzB;iBACF,CAAC,CAAC;YACL,CAAC;QACH,CAAC;IACH,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,qBAAqB,CAAC,QAA+B;IACnE,MAAM,MAAM,GAA+B,EAAE,CAAC;IAE9C,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,MAAM,CAAC,IAAI,CAAC,GAAG,kBAAkB,CAAC,OAAO,CAAC,CAAC,CAAC;IAC9C,CAAC;IAED,OAAO,MAAM,CAAC;AAChB,CAAC"}
@@ -0,0 +1,49 @@
1
+ /**
2
+ * HTML Nesting Validator
3
+ *
4
+ * Validates parent/child relationships of Coherent.js elements
5
+ * against HTML5 content model rules.
6
+ */
7
+ import { Range } from 'vscode-languageserver';
8
+ import { CoherentElementInfo } from './coherent-analyzer.js';
9
+ /**
10
+ * Nesting validation error.
11
+ */
12
+ export interface NestingValidationError {
13
+ /** Error message */
14
+ message: string;
15
+ /** Source range of the error */
16
+ range: Range;
17
+ /** Error code for categorization */
18
+ code: 'invalid-nesting' | 'invalid-parent' | 'block-in-inline' | 'invalid-child';
19
+ /** Severity of the error */
20
+ severity: 'error' | 'warning';
21
+ /** The child element tag name */
22
+ childTag: string;
23
+ /** The parent element tag name */
24
+ parentTag: string;
25
+ /** Additional data for code actions */
26
+ data?: Record<string, unknown>;
27
+ }
28
+ /**
29
+ * Validate nesting of an element within its parent.
30
+ *
31
+ * @param element - The Coherent element to validate
32
+ * @returns Array of nesting validation errors
33
+ */
34
+ export declare function validateElementNesting(element: CoherentElementInfo): NestingValidationError[];
35
+ /**
36
+ * Validate nesting for multiple elements.
37
+ *
38
+ * @param elements - Array of Coherent elements to validate
39
+ * @returns Array of all nesting validation errors
40
+ */
41
+ export declare function validateAllNesting(elements: CoherentElementInfo[]): NestingValidationError[];
42
+ /**
43
+ * Get suggestions for fixing nesting errors.
44
+ *
45
+ * @param error - The nesting validation error
46
+ * @returns Suggested fix description or null
47
+ */
48
+ export declare function getNestingFixSuggestion(error: NestingValidationError): string | null;
49
+ //# sourceMappingURL=nesting-validator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nesting-validator.d.ts","sourceRoot":"","sources":["../../src/analysis/nesting-validator.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAC9C,OAAO,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAC;AAG7D;;GAEG;AACH,MAAM,WAAW,sBAAsB;IACrC,oBAAoB;IACpB,OAAO,EAAE,MAAM,CAAC;IAEhB,gCAAgC;IAChC,KAAK,EAAE,KAAK,CAAC;IAEb,oCAAoC;IACpC,IAAI,EAAE,iBAAiB,GAAG,gBAAgB,GAAG,iBAAiB,GAAG,eAAe,CAAC;IAEjF,4BAA4B;IAC5B,QAAQ,EAAE,OAAO,GAAG,SAAS,CAAC;IAE9B,iCAAiC;IACjC,QAAQ,EAAE,MAAM,CAAC;IAEjB,kCAAkC;IAClC,SAAS,EAAE,MAAM,CAAC;IAElB,uCAAuC;IACvC,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAChC;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CAAC,OAAO,EAAE,mBAAmB,GAAG,sBAAsB,EAAE,CAuB7F;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,QAAQ,EAAE,mBAAmB,EAAE,GAAG,sBAAsB,EAAE,CAQ5F;AAED;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,sBAAsB,GAAG,MAAM,GAAG,IAAI,CAiBpF"}