coherent-language-support 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 (55) hide show
  1. package/.vscodeignore +8 -0
  2. package/CHANGELOG.md +14 -0
  3. package/LICENSE +21 -0
  4. package/README.md +108 -0
  5. package/coherent-language-support-1.0.0.vsix +0 -0
  6. package/dist/extension.js +18075 -0
  7. package/dist/extension.js.map +7 -0
  8. package/esbuild.config.mjs +24 -0
  9. package/icon.png +0 -0
  10. package/icon.svg +10 -0
  11. package/package.json +78 -0
  12. package/server/analysis/coherent-analyzer.d.ts +93 -0
  13. package/server/analysis/coherent-analyzer.d.ts.map +1 -0
  14. package/server/analysis/coherent-analyzer.js +288 -0
  15. package/server/analysis/coherent-analyzer.js.map +1 -0
  16. package/server/analysis/element-validator.d.ts +45 -0
  17. package/server/analysis/element-validator.d.ts.map +1 -0
  18. package/server/analysis/element-validator.js +84 -0
  19. package/server/analysis/element-validator.js.map +1 -0
  20. package/server/analysis/nesting-validator.d.ts +49 -0
  21. package/server/analysis/nesting-validator.d.ts.map +1 -0
  22. package/server/analysis/nesting-validator.js +68 -0
  23. package/server/analysis/nesting-validator.js.map +1 -0
  24. package/server/data/element-attributes.d.ts +92 -0
  25. package/server/data/element-attributes.d.ts.map +1 -0
  26. package/server/data/element-attributes.generated.json +7085 -0
  27. package/server/data/element-attributes.js +282 -0
  28. package/server/data/element-attributes.js.map +1 -0
  29. package/server/data/nesting-rules.d.ts +67 -0
  30. package/server/data/nesting-rules.d.ts.map +1 -0
  31. package/server/data/nesting-rules.js +240 -0
  32. package/server/data/nesting-rules.js.map +1 -0
  33. package/server/providers/code-actions.d.ts +15 -0
  34. package/server/providers/code-actions.d.ts.map +1 -0
  35. package/server/providers/code-actions.js +191 -0
  36. package/server/providers/code-actions.js.map +1 -0
  37. package/server/providers/completion.d.ts +15 -0
  38. package/server/providers/completion.d.ts.map +1 -0
  39. package/server/providers/completion.js +247 -0
  40. package/server/providers/completion.js.map +1 -0
  41. package/server/providers/diagnostics.d.ts +26 -0
  42. package/server/providers/diagnostics.d.ts.map +1 -0
  43. package/server/providers/diagnostics.js +143 -0
  44. package/server/providers/diagnostics.js.map +1 -0
  45. package/server/providers/hover.d.ts +15 -0
  46. package/server/providers/hover.d.ts.map +1 -0
  47. package/server/providers/hover.js +215 -0
  48. package/server/providers/hover.js.map +1 -0
  49. package/server/server.d.ts +17 -0
  50. package/server/server.d.ts.map +1 -0
  51. package/server/server.js +82 -0
  52. package/server/server.js.map +1 -0
  53. package/snippets/coherent.json +226 -0
  54. package/src/extension.ts +75 -0
  55. package/tsconfig.json +18 -0
@@ -0,0 +1,15 @@
1
+ /**
2
+ * Hover Provider
3
+ *
4
+ * Provides hover information (documentation) for Coherent.js elements and attributes.
5
+ */
6
+ import { Connection, TextDocuments } from 'vscode-languageserver';
7
+ import { TextDocument } from 'vscode-languageserver-textdocument';
8
+ /**
9
+ * Register the hover provider.
10
+ *
11
+ * @param connection - LSP connection
12
+ * @param documents - Text document manager
13
+ */
14
+ export declare function registerHoverProvider(connection: Connection, documents: TextDocuments<TextDocument>): void;
15
+ //# sourceMappingURL=hover.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hover.d.ts","sourceRoot":"","sources":["../../src/providers/hover.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EACL,UAAU,EACV,aAAa,EAId,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,YAAY,EAAE,MAAM,oCAAoC,CAAC;AAalE;;;;;GAKG;AACH,wBAAgB,qBAAqB,CACnC,UAAU,EAAE,UAAU,EACtB,SAAS,EAAE,aAAa,CAAC,YAAY,CAAC,GACrC,IAAI,CAuCN"}
@@ -0,0 +1,215 @@
1
+ /**
2
+ * Hover Provider
3
+ *
4
+ * Provides hover information (documentation) for Coherent.js elements and attributes.
5
+ */
6
+ import { MarkupKind, } from 'vscode-languageserver';
7
+ import { createSourceFile, getPositionContext, } from '../analysis/coherent-analyzer.js';
8
+ import { getElementDescription, getAttributeType, getAttributeDescription, getAttributesForElement, isVoidElement, } from '../data/element-attributes.js';
9
+ /**
10
+ * Register the hover provider.
11
+ *
12
+ * @param connection - LSP connection
13
+ * @param documents - Text document manager
14
+ */
15
+ export function registerHoverProvider(connection, documents) {
16
+ connection.onHover((params) => {
17
+ const document = documents.get(params.textDocument.uri);
18
+ if (!document) {
19
+ return null;
20
+ }
21
+ try {
22
+ const content = document.getText();
23
+ const sourceFile = createSourceFile(content, params.textDocument.uri);
24
+ const context = getPositionContext(sourceFile, params.position);
25
+ switch (context.type) {
26
+ case 'tag-name':
27
+ if (context.element) {
28
+ return createElementHover(context.element.tagName);
29
+ }
30
+ break;
31
+ case 'attribute-name':
32
+ if (context.element && context.attribute) {
33
+ return createAttributeHover(context.element.tagName, context.attribute.name);
34
+ }
35
+ break;
36
+ case 'attribute-value':
37
+ // Could show value type information
38
+ break;
39
+ default:
40
+ break;
41
+ }
42
+ return null;
43
+ }
44
+ catch (error) {
45
+ console.error('[coherent-lsp] Hover error:', error);
46
+ return null;
47
+ }
48
+ });
49
+ }
50
+ /**
51
+ * Create hover content for an HTML element.
52
+ */
53
+ function createElementHover(tagName) {
54
+ const description = getElementDescription(tagName);
55
+ const isVoid = isVoidElement(tagName);
56
+ const attrs = getAttributesForElement(tagName);
57
+ let markdown = `## <${tagName}>\n\n`;
58
+ markdown += `${description}\n\n`;
59
+ if (isVoid) {
60
+ markdown += `> **Void element** - cannot have children\n\n`;
61
+ }
62
+ // Example usage
63
+ markdown += `### Example\n\n`;
64
+ markdown += '```javascript\n';
65
+ if (isVoid) {
66
+ markdown += `{ ${tagName}: { /* attributes */ } }\n`;
67
+ }
68
+ else {
69
+ markdown += `{ ${tagName}: {\n`;
70
+ markdown += ` className: 'example',\n`;
71
+ markdown += ` children: [/* child elements */]\n`;
72
+ markdown += `} }\n`;
73
+ }
74
+ markdown += '```\n\n';
75
+ // Common attributes
76
+ const elementSpecificAttrs = attrs.filter(a => !['id', 'className', 'class', 'style', 'title', 'hidden', 'tabIndex',
77
+ 'text', 'html', 'children', 'key'].includes(a.name) &&
78
+ !a.name.startsWith('on') &&
79
+ !a.name.startsWith('aria-') &&
80
+ !a.name.startsWith('data-')).slice(0, 8);
81
+ if (elementSpecificAttrs.length > 0) {
82
+ markdown += `### Element-Specific Attributes\n\n`;
83
+ for (const attr of elementSpecificAttrs) {
84
+ markdown += `- \`${attr.name}\`: \`${attr.type}\`\n`;
85
+ }
86
+ markdown += '\n';
87
+ }
88
+ return {
89
+ contents: {
90
+ kind: MarkupKind.Markdown,
91
+ value: markdown,
92
+ },
93
+ };
94
+ }
95
+ /**
96
+ * Create hover content for an attribute.
97
+ */
98
+ function createAttributeHover(tagName, attributeName) {
99
+ const type = getAttributeType(tagName, attributeName);
100
+ const description = getAttributeDescription(tagName, attributeName);
101
+ let markdown = `## ${attributeName}\n\n`;
102
+ // Type information
103
+ if (type) {
104
+ markdown += `**Type:** \`${type}\`\n\n`;
105
+ }
106
+ // Description
107
+ if (description) {
108
+ markdown += `${description}\n\n`;
109
+ }
110
+ // Special handling for common attributes
111
+ const examples = getAttributeExamples(attributeName, type);
112
+ if (examples) {
113
+ markdown += `### Examples\n\n`;
114
+ markdown += '```javascript\n';
115
+ markdown += examples;
116
+ markdown += '\n```\n';
117
+ }
118
+ // Event handler information
119
+ if (attributeName.startsWith('on') && attributeName[2] === attributeName[2].toUpperCase()) {
120
+ const eventType = getEventType(attributeName);
121
+ if (eventType) {
122
+ markdown += `\n**Event type:** \`${eventType}\`\n`;
123
+ }
124
+ }
125
+ return {
126
+ contents: {
127
+ kind: MarkupKind.Markdown,
128
+ value: markdown,
129
+ },
130
+ };
131
+ }
132
+ /**
133
+ * Get example usage for common attributes.
134
+ */
135
+ function getAttributeExamples(attributeName, type) {
136
+ const examples = {
137
+ className: "className: 'my-class another-class'",
138
+ id: "id: 'unique-id'",
139
+ style: "style: { color: 'red', fontSize: '16px' }",
140
+ onClick: "onClick: (event) => {\n console.log('Clicked!', event);\n}",
141
+ onChange: "onChange: (event) => {\n const value = event.target.value;\n}",
142
+ onSubmit: "onSubmit: (event) => {\n event.preventDefault();\n // Handle form submission\n}",
143
+ children: "children: [\n { span: { text: 'Child 1' } },\n { span: { text: 'Child 2' } }\n]",
144
+ text: "text: 'Text content (escaped)'",
145
+ html: "html: '<strong>Raw HTML</strong>' // Use with caution!",
146
+ key: "key: 'unique-item-key'",
147
+ href: "href: 'https://example.com'",
148
+ src: "src: '/images/photo.jpg'",
149
+ alt: "alt: 'Description of the image'",
150
+ type: "type: 'submit' // or 'button', 'text', etc.",
151
+ value: "value: 'input value'",
152
+ placeholder: "placeholder: 'Enter text...'",
153
+ disabled: "disabled: true",
154
+ checked: "checked: true",
155
+ required: "required: true",
156
+ name: "name: 'field-name'",
157
+ };
158
+ return examples[attributeName] || null;
159
+ }
160
+ /**
161
+ * Get the DOM event type for an event handler.
162
+ */
163
+ function getEventType(handlerName) {
164
+ const eventTypes = {
165
+ onClick: 'MouseEvent',
166
+ onDblClick: 'MouseEvent',
167
+ onMouseDown: 'MouseEvent',
168
+ onMouseUp: 'MouseEvent',
169
+ onMouseEnter: 'MouseEvent',
170
+ onMouseLeave: 'MouseEvent',
171
+ onMouseMove: 'MouseEvent',
172
+ onMouseOver: 'MouseEvent',
173
+ onMouseOut: 'MouseEvent',
174
+ onContextMenu: 'MouseEvent',
175
+ onKeyDown: 'KeyboardEvent',
176
+ onKeyUp: 'KeyboardEvent',
177
+ onKeyPress: 'KeyboardEvent',
178
+ onFocus: 'FocusEvent',
179
+ onBlur: 'FocusEvent',
180
+ onFocusIn: 'FocusEvent',
181
+ onFocusOut: 'FocusEvent',
182
+ onChange: 'Event',
183
+ onInput: 'Event',
184
+ onSubmit: 'SubmitEvent',
185
+ onReset: 'Event',
186
+ onInvalid: 'Event',
187
+ onDrag: 'DragEvent',
188
+ onDragEnd: 'DragEvent',
189
+ onDragEnter: 'DragEvent',
190
+ onDragLeave: 'DragEvent',
191
+ onDragOver: 'DragEvent',
192
+ onDragStart: 'DragEvent',
193
+ onDrop: 'DragEvent',
194
+ onCopy: 'ClipboardEvent',
195
+ onCut: 'ClipboardEvent',
196
+ onPaste: 'ClipboardEvent',
197
+ onTouchStart: 'TouchEvent',
198
+ onTouchMove: 'TouchEvent',
199
+ onTouchEnd: 'TouchEvent',
200
+ onTouchCancel: 'TouchEvent',
201
+ onWheel: 'WheelEvent',
202
+ onScroll: 'Event',
203
+ onAnimationStart: 'AnimationEvent',
204
+ onAnimationEnd: 'AnimationEvent',
205
+ onAnimationIteration: 'AnimationEvent',
206
+ onTransitionStart: 'TransitionEvent',
207
+ onTransitionEnd: 'TransitionEvent',
208
+ onTransitionCancel: 'TransitionEvent',
209
+ onTransitionRun: 'TransitionEvent',
210
+ onLoad: 'Event',
211
+ onError: 'Event',
212
+ };
213
+ return eventTypes[handlerName] || null;
214
+ }
215
+ //# sourceMappingURL=hover.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hover.js","sourceRoot":"","sources":["../../src/providers/hover.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Coherent.js Language Server
4
+ *
5
+ * Provides Language Server Protocol (LSP) support for Coherent.js components:
6
+ * - Autocomplete for tag names and attributes
7
+ * - Validation of attributes and HTML nesting
8
+ * - Hover documentation for elements and attributes
9
+ * - Quick fix code actions for common issues
10
+ *
11
+ * @see https://microsoft.github.io/language-server-protocol/
12
+ */
13
+ import { TextDocuments } from 'vscode-languageserver/node.js';
14
+ import { TextDocument } from 'vscode-languageserver-textdocument';
15
+ export declare const connection: import("vscode-languageserver/node.js")._Connection<import("vscode-languageserver/node.js")._, import("vscode-languageserver/node.js")._, import("vscode-languageserver/node.js")._, import("vscode-languageserver/node.js")._, import("vscode-languageserver/node.js")._, import("vscode-languageserver/node.js")._, import("vscode-languageserver/lib/common/inlineCompletion.proposed.js").InlineCompletionFeatureShape, import("vscode-languageserver/node.js")._>;
16
+ export declare const documents: TextDocuments<TextDocument>;
17
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":";AACA;;;;;;;;;;GAUG;AAEH,OAAO,EAEL,aAAa,EAOd,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAAE,YAAY,EAAE,MAAM,oCAAoC,CAAC;AASlE,eAAO,MAAM,UAAU,wcAAyC,CAAC;AAGjE,eAAO,MAAM,SAAS,EAAE,aAAa,CAAC,YAAY,CAAmC,CAAC"}
@@ -0,0 +1,82 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Coherent.js Language Server
4
+ *
5
+ * Provides Language Server Protocol (LSP) support for Coherent.js components:
6
+ * - Autocomplete for tag names and attributes
7
+ * - Validation of attributes and HTML nesting
8
+ * - Hover documentation for elements and attributes
9
+ * - Quick fix code actions for common issues
10
+ *
11
+ * @see https://microsoft.github.io/language-server-protocol/
12
+ */
13
+ import { createConnection, TextDocuments, ProposedFeatures, TextDocumentSyncKind, CodeActionKind, DidChangeConfigurationNotification, } from 'vscode-languageserver/node.js';
14
+ import { TextDocument } from 'vscode-languageserver-textdocument';
15
+ // Import providers
16
+ import { registerDiagnosticProvider } from './providers/diagnostics.js';
17
+ import { registerCompletionProvider } from './providers/completion.js';
18
+ import { registerHoverProvider } from './providers/hover.js';
19
+ import { registerCodeActionProvider } from './providers/code-actions.js';
20
+ // Create connection using all proposed features
21
+ export const connection = createConnection(ProposedFeatures.all);
22
+ // Text document manager for syncing documents
23
+ export const documents = new TextDocuments(TextDocument);
24
+ // Server capabilities
25
+ let hasConfigurationCapability = false;
26
+ let hasWorkspaceFolderCapability = false;
27
+ connection.onInitialize((params) => {
28
+ const capabilities = params.capabilities;
29
+ // Check client capabilities
30
+ hasConfigurationCapability = !!(capabilities.workspace && !!capabilities.workspace.configuration);
31
+ hasWorkspaceFolderCapability = !!(capabilities.workspace && !!capabilities.workspace.workspaceFolders);
32
+ const result = {
33
+ capabilities: {
34
+ // Incremental document sync for performance
35
+ textDocumentSync: TextDocumentSyncKind.Incremental,
36
+ // Autocomplete provider
37
+ completionProvider: {
38
+ resolveProvider: true,
39
+ triggerCharacters: ['{', ':', '"', "'"],
40
+ },
41
+ // Hover provider for documentation
42
+ hoverProvider: true,
43
+ // Code action provider for quick fixes
44
+ codeActionProvider: {
45
+ codeActionKinds: [CodeActionKind.QuickFix],
46
+ },
47
+ },
48
+ };
49
+ // Add workspace folder support if available
50
+ if (hasWorkspaceFolderCapability) {
51
+ result.capabilities.workspace = {
52
+ workspaceFolders: {
53
+ supported: true,
54
+ },
55
+ };
56
+ }
57
+ // Log capabilities for debugging
58
+ console.error('[coherent-lsp] Initialized with capabilities:', JSON.stringify(result.capabilities, null, 2));
59
+ return result;
60
+ });
61
+ connection.onInitialized(() => {
62
+ if (hasConfigurationCapability) {
63
+ // Register for configuration changes
64
+ connection.client.register(DidChangeConfigurationNotification.type, undefined);
65
+ }
66
+ if (hasWorkspaceFolderCapability) {
67
+ connection.workspace.onDidChangeWorkspaceFolders((_event) => {
68
+ console.error('[coherent-lsp] Workspace folder change event received');
69
+ });
70
+ }
71
+ // Register providers
72
+ registerDiagnosticProvider(connection, documents);
73
+ registerCompletionProvider(connection, documents);
74
+ registerHoverProvider(connection, documents);
75
+ registerCodeActionProvider(connection, documents);
76
+ console.error('[coherent-lsp] Server initialized successfully');
77
+ });
78
+ // Start listening for document events
79
+ documents.listen(connection);
80
+ // Start the connection
81
+ connection.listen();
82
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,226 @@
1
+ {
2
+ "Coherent Element": {
3
+ "prefix": "cel",
4
+ "body": [
5
+ "{ ${1:div}: {",
6
+ "\tclassName: '${2:class}',",
7
+ "\t${3:children: [",
8
+ "\t\t$0",
9
+ "\t]}",
10
+ "}}"
11
+ ],
12
+ "description": "Create a Coherent.js element"
13
+ },
14
+ "Coherent Component": {
15
+ "prefix": "ccomp",
16
+ "body": [
17
+ "const ${1:ComponentName} = (${2:props}) => ({",
18
+ "\t${3:div}: {",
19
+ "\t\tclassName: '${4:component-class}',",
20
+ "\t\tchildren: [",
21
+ "\t\t\t$0",
22
+ "\t\t]",
23
+ "\t}",
24
+ "});",
25
+ "",
26
+ "export { ${1:ComponentName} };"
27
+ ],
28
+ "description": "Create a Coherent.js functional component"
29
+ },
30
+ "Coherent Text": {
31
+ "prefix": "ctext",
32
+ "body": [
33
+ "{ ${1:p}: { text: '${2:content}' }}"
34
+ ],
35
+ "description": "Create a text element"
36
+ },
37
+ "Coherent Link": {
38
+ "prefix": "clink",
39
+ "body": [
40
+ "{ a: {",
41
+ "\thref: '${1:/path}',",
42
+ "\ttext: '${2:Link text}'",
43
+ "}}"
44
+ ],
45
+ "description": "Create an anchor element"
46
+ },
47
+ "Coherent Image": {
48
+ "prefix": "cimg",
49
+ "body": [
50
+ "{ img: {",
51
+ "\tsrc: '${1:url}',",
52
+ "\talt: '${2:description}'",
53
+ "}}"
54
+ ],
55
+ "description": "Create an image element"
56
+ },
57
+ "Coherent Input": {
58
+ "prefix": "cinput",
59
+ "body": [
60
+ "{ input: {",
61
+ "\ttype: '${1|text,email,password,number,checkbox,radio|}',",
62
+ "\tname: '${2:fieldName}',",
63
+ "\tplaceholder: '${3:Enter value}'",
64
+ "}}"
65
+ ],
66
+ "description": "Create an input element"
67
+ },
68
+ "Coherent Button": {
69
+ "prefix": "cbtn",
70
+ "body": [
71
+ "{ button: {",
72
+ "\ttype: '${1|button,submit,reset|}',",
73
+ "\tclassName: '${2:btn}',",
74
+ "\ttext: '${3:Click me}'",
75
+ "}}"
76
+ ],
77
+ "description": "Create a button element"
78
+ },
79
+ "Coherent Form": {
80
+ "prefix": "cform",
81
+ "body": [
82
+ "{ form: {",
83
+ "\tmethod: '${1|POST,GET|}',",
84
+ "\taction: '${2:/api/submit}',",
85
+ "\tchildren: [",
86
+ "\t\t$0",
87
+ "\t]",
88
+ "}}"
89
+ ],
90
+ "description": "Create a form element"
91
+ },
92
+ "Coherent List": {
93
+ "prefix": "clist",
94
+ "body": [
95
+ "{ ${1|ul,ol|}: {",
96
+ "\tchildren: ${2:items}.map((${3:item}) => ({",
97
+ "\t\tli: { text: ${3:item} }",
98
+ "\t}))",
99
+ "}}"
100
+ ],
101
+ "description": "Create a list with mapped items"
102
+ },
103
+ "Coherent Conditional": {
104
+ "prefix": "cif",
105
+ "body": [
106
+ "${1:condition} ? { ${2:div}: { text: '${3:shown}' }} : null"
107
+ ],
108
+ "description": "Conditional rendering pattern"
109
+ },
110
+ "Coherent Event Handler": {
111
+ "prefix": "cevent",
112
+ "body": [
113
+ "on${1|Click,Change,Submit,Focus,Blur|}: '${2:handlerName}'"
114
+ ],
115
+ "description": "Add an event handler"
116
+ },
117
+ "Coherent Data Attributes": {
118
+ "prefix": "cdata",
119
+ "body": [
120
+ "'data-${1:name}': '${2:value}'"
121
+ ],
122
+ "description": "Add a data attribute"
123
+ },
124
+ "Coherent Page Layout": {
125
+ "prefix": "cpage",
126
+ "body": [
127
+ "const ${1:PageName} = () => ({",
128
+ "\thtml: {",
129
+ "\t\tlang: 'en',",
130
+ "\t\tchildren: [",
131
+ "\t\t\t{ head: {",
132
+ "\t\t\t\tchildren: [",
133
+ "\t\t\t\t\t{ meta: { charset: 'utf-8' }},",
134
+ "\t\t\t\t\t{ meta: { name: 'viewport', content: 'width=device-width, initial-scale=1' }},",
135
+ "\t\t\t\t\t{ title: { text: '${2:Page Title}' }}",
136
+ "\t\t\t\t]",
137
+ "\t\t\t}},",
138
+ "\t\t\t{ body: {",
139
+ "\t\t\t\tchildren: [",
140
+ "\t\t\t\t\t$0",
141
+ "\t\t\t\t]",
142
+ "\t\t\t}}",
143
+ "\t\t]",
144
+ "\t}",
145
+ "});",
146
+ "",
147
+ "export { ${1:PageName} };"
148
+ ],
149
+ "description": "Create a full page layout"
150
+ },
151
+ "Coherent Card": {
152
+ "prefix": "ccard",
153
+ "body": [
154
+ "{ div: {",
155
+ "\tclassName: '${1:card}',",
156
+ "\tchildren: [",
157
+ "\t\t{ ${2:img}: { src: '${3:url}', alt: '${4:description}' }},",
158
+ "\t\t{ div: {",
159
+ "\t\t\tclassName: '${1:card}-body',",
160
+ "\t\t\tchildren: [",
161
+ "\t\t\t\t{ h3: { text: '${5:Title}' }},",
162
+ "\t\t\t\t{ p: { text: '${6:Description}' }}",
163
+ "\t\t\t]",
164
+ "\t\t}}",
165
+ "\t]",
166
+ "}}"
167
+ ],
168
+ "description": "Create a card component structure"
169
+ },
170
+ "Coherent Table": {
171
+ "prefix": "ctable",
172
+ "body": [
173
+ "{ table: {",
174
+ "\tchildren: [",
175
+ "\t\t{ thead: {",
176
+ "\t\t\tchildren: [",
177
+ "\t\t\t\t{ tr: {",
178
+ "\t\t\t\t\tchildren: [",
179
+ "\t\t\t\t\t\t{ th: { text: '${1:Column 1}' }},",
180
+ "\t\t\t\t\t\t{ th: { text: '${2:Column 2}' }}",
181
+ "\t\t\t\t\t]",
182
+ "\t\t\t\t}}",
183
+ "\t\t\t]",
184
+ "\t\t}},",
185
+ "\t\t{ tbody: {",
186
+ "\t\t\tchildren: ${3:data}.map((${4:row}) => ({",
187
+ "\t\t\t\ttr: {",
188
+ "\t\t\t\t\tchildren: [",
189
+ "\t\t\t\t\t\t{ td: { text: ${4:row}.${5:field1} }},",
190
+ "\t\t\t\t\t\t{ td: { text: ${4:row}.${6:field2} }}",
191
+ "\t\t\t\t\t]",
192
+ "\t\t\t\t}",
193
+ "\t\t\t}))",
194
+ "\t\t}}",
195
+ "\t]",
196
+ "}}"
197
+ ],
198
+ "description": "Create a table with header and mapped body"
199
+ },
200
+ "Coherent Render Import": {
201
+ "prefix": "cimport",
202
+ "body": [
203
+ "import { ${1|render,renderToString,createComponent|} } from '@coherent.js/core';"
204
+ ],
205
+ "description": "Import Coherent.js core functions"
206
+ },
207
+ "Coherent Server Setup": {
208
+ "prefix": "cserver",
209
+ "body": [
210
+ "import { render } from '@coherent.js/core';",
211
+ "import { createServer } from '@coherent.js/${1|express,fastify,koa|}';",
212
+ "",
213
+ "const app = createServer();",
214
+ "",
215
+ "app.get('/', (req, res) => {",
216
+ "\tconst html = render({ div: { text: 'Hello, Coherent.js!' }});",
217
+ "\tres.send(html);",
218
+ "});",
219
+ "",
220
+ "app.listen(${2:3000}, () => {",
221
+ "\tconsole.log('Server running on port ${2:3000}');",
222
+ "});"
223
+ ],
224
+ "description": "Create a basic Coherent.js server"
225
+ }
226
+ }
@@ -0,0 +1,75 @@
1
+ import * as path from 'path';
2
+ import { ExtensionContext, workspace } from 'vscode';
3
+ import {
4
+ LanguageClient,
5
+ LanguageClientOptions,
6
+ ServerOptions,
7
+ TransportKind,
8
+ } from 'vscode-languageclient/node';
9
+
10
+ let client: LanguageClient | undefined;
11
+
12
+ export function activate(context: ExtensionContext): void {
13
+ // Server is BUNDLED with extension in server/ directory
14
+ // This avoids npm dependency resolution issues and works offline
15
+ const serverModule = context.asAbsolutePath(path.join('server', 'server.js'));
16
+
17
+ // Server options - use IPC for better performance
18
+ const serverOptions: ServerOptions = {
19
+ run: {
20
+ module: serverModule,
21
+ transport: TransportKind.ipc,
22
+ },
23
+ debug: {
24
+ module: serverModule,
25
+ transport: TransportKind.ipc,
26
+ options: {
27
+ execArgv: ['--nolazy', '--inspect=6009'],
28
+ },
29
+ },
30
+ };
31
+
32
+ // Client options
33
+ const clientOptions: LanguageClientOptions = {
34
+ // Register for JavaScript and TypeScript files
35
+ documentSelector: [
36
+ { scheme: 'file', language: 'javascript' },
37
+ { scheme: 'file', language: 'typescript' },
38
+ { scheme: 'file', language: 'javascriptreact' },
39
+ { scheme: 'file', language: 'typescriptreact' },
40
+ ],
41
+ synchronize: {
42
+ // Synchronize the setting section 'coherent' to the server
43
+ configurationSection: 'coherent',
44
+ // Notify the server about file changes
45
+ fileEvents: workspace.createFileSystemWatcher('**/*.{js,ts,jsx,tsx}'),
46
+ },
47
+ };
48
+
49
+ // Create and start the language client
50
+ client = new LanguageClient(
51
+ 'coherentLanguageServer',
52
+ 'Coherent.js Language Server',
53
+ serverOptions,
54
+ clientOptions
55
+ );
56
+
57
+ // Start the client (also launches the server)
58
+ client.start();
59
+
60
+ // Push client to subscriptions for cleanup on deactivation
61
+ context.subscriptions.push({
62
+ dispose: () => {
63
+ if (client) {
64
+ client.stop();
65
+ }
66
+ },
67
+ });
68
+ }
69
+
70
+ export function deactivate(): Thenable<void> | undefined {
71
+ if (!client) {
72
+ return undefined;
73
+ }
74
+ return client.stop();
75
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,18 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2022",
4
+ "module": "NodeNext",
5
+ "moduleResolution": "NodeNext",
6
+ "lib": ["ES2022"],
7
+ "outDir": "dist",
8
+ "rootDir": "src",
9
+ "strict": true,
10
+ "esModuleInterop": true,
11
+ "skipLibCheck": true,
12
+ "declaration": true,
13
+ "declarationMap": true,
14
+ "sourceMap": true
15
+ },
16
+ "include": ["src/**/*"],
17
+ "exclude": ["node_modules", "dist"]
18
+ }