@formspec/language-server 0.1.0-alpha.13 → 0.1.0-alpha.16

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/README.md CHANGED
@@ -39,17 +39,17 @@ This package provides language server features for FormSpec's JSDoc constraint t
39
39
 
40
40
  - **Completion** — Autocomplete for constraint tag names inside JSDoc comments
41
41
  - **Hover** — Documentation on hover for constraint tags
42
- - **Go to Definition** — Navigate to constraint definitions *(placeholder — not yet implemented)*
42
+ - **Go to Definition** — Navigate to constraint definitions _(placeholder — not yet implemented)_
43
43
 
44
44
  ## API Reference
45
45
 
46
46
  ### Functions
47
47
 
48
- | Function | Description |
49
- | --- | --- |
50
- | `createServer()` | Create a full LSP server connection |
51
- | `getCompletionItems()` | Get completion items for constraint tags |
52
- | `getDefinition()` | Get definition location for a constraint tag |
48
+ | Function | Description |
49
+ | ------------------------- | ----------------------------------------------- |
50
+ | `createServer()` | Create a full LSP server connection |
51
+ | `getCompletionItems()` | Get completion items for constraint tags |
52
+ | `getDefinition()` | Get definition location for a constraint tag |
53
53
  | `getHoverForTag(tagName)` | Get hover information for a constraint tag name |
54
54
 
55
55
  ### `createServer()`
package/dist/index.cjs CHANGED
@@ -31,30 +31,36 @@ module.exports = __toCommonJS(index_exports);
31
31
  var import_node2 = require("vscode-languageserver/node.js");
32
32
 
33
33
  // src/providers/completion.ts
34
+ var import_core = require("@formspec/core");
34
35
  var import_node = require("vscode-languageserver/node.js");
35
36
  var CONSTRAINT_DETAIL = {
36
- Minimum: "Minimum numeric value (inclusive). Example: `@Minimum 0`",
37
- Maximum: "Maximum numeric value (inclusive). Example: `@Maximum 100`",
38
- ExclusiveMinimum: "Minimum numeric value (exclusive). Example: `@ExclusiveMinimum 0`",
39
- ExclusiveMaximum: "Maximum numeric value (exclusive). Example: `@ExclusiveMaximum 100`",
40
- MinLength: "Minimum string length. Example: `@MinLength 1`",
41
- MaxLength: "Maximum string length. Example: `@MaxLength 255`",
42
- Pattern: "Regular expression pattern for string validation. Example: `@Pattern ^[a-z]+$`",
43
- EnumOptions: 'Inline JSON array of allowed enum values. Example: `@EnumOptions ["a","b","c"]`'
37
+ minimum: "Minimum numeric value (inclusive). Example: `@minimum 0`",
38
+ maximum: "Maximum numeric value (inclusive). Example: `@maximum 100`",
39
+ exclusiveMinimum: "Minimum numeric value (exclusive). Example: `@exclusiveMinimum 0`",
40
+ exclusiveMaximum: "Maximum numeric value (exclusive). Example: `@exclusiveMaximum 100`",
41
+ multipleOf: "Value must be a multiple of this number. Example: `@multipleOf 0.01`",
42
+ minLength: "Minimum string length. Example: `@minLength 1`",
43
+ maxLength: "Maximum string length. Example: `@maxLength 255`",
44
+ minItems: "Minimum number of array items. Example: `@minItems 1`",
45
+ maxItems: "Maximum number of array items. Example: `@maxItems 10`",
46
+ uniqueItems: "Require all array items to be distinct. Example: `@uniqueItems`",
47
+ pattern: "Regular expression pattern for string validation. Example: `@pattern ^[a-z]+$`",
48
+ enumOptions: 'Inline JSON array of allowed enum values. Example: `@enumOptions ["a","b","c"]`',
49
+ const: 'Require a constant JSON value. Example: `@const "USD"`'
44
50
  };
45
51
  function getCompletionItems() {
46
- return Object.entries(CONSTRAINT_DETAIL).map(([name, detail]) => ({
52
+ return Object.keys(import_core.BUILTIN_CONSTRAINT_DEFINITIONS).map((name) => ({
47
53
  label: `@${name}`,
48
54
  kind: import_node.CompletionItemKind.Keyword,
49
- detail
55
+ detail: CONSTRAINT_DETAIL[name]
50
56
  }));
51
57
  }
52
58
 
53
59
  // src/providers/hover.ts
54
- var import_core = require("@formspec/core");
60
+ var import_core2 = require("@formspec/core");
55
61
  var CONSTRAINT_HOVER_DOCS = {
56
- Minimum: [
57
- "**@Minimum** `<number>`",
62
+ minimum: [
63
+ "**@minimum** `<number>`",
58
64
  "",
59
65
  "Sets an inclusive lower bound on a numeric field.",
60
66
  "",
@@ -62,12 +68,12 @@ var CONSTRAINT_HOVER_DOCS = {
62
68
  "",
63
69
  "**Example:**",
64
70
  "```typescript",
65
- "/** @Minimum 0 */",
71
+ "/** @minimum 0 */",
66
72
  "amount: number;",
67
73
  "```"
68
74
  ].join("\n"),
69
- Maximum: [
70
- "**@Maximum** `<number>`",
75
+ maximum: [
76
+ "**@maximum** `<number>`",
71
77
  "",
72
78
  "Sets an inclusive upper bound on a numeric field.",
73
79
  "",
@@ -75,12 +81,12 @@ var CONSTRAINT_HOVER_DOCS = {
75
81
  "",
76
82
  "**Example:**",
77
83
  "```typescript",
78
- "/** @Maximum 100 */",
84
+ "/** @maximum 100 */",
79
85
  "percentage: number;",
80
86
  "```"
81
87
  ].join("\n"),
82
- ExclusiveMinimum: [
83
- "**@ExclusiveMinimum** `<number>`",
88
+ exclusiveMinimum: [
89
+ "**@exclusiveMinimum** `<number>`",
84
90
  "",
85
91
  "Sets an exclusive lower bound on a numeric field.",
86
92
  "",
@@ -88,12 +94,12 @@ var CONSTRAINT_HOVER_DOCS = {
88
94
  "",
89
95
  "**Example:**",
90
96
  "```typescript",
91
- "/** @ExclusiveMinimum 0 */",
97
+ "/** @exclusiveMinimum 0 */",
92
98
  "positiveAmount: number;",
93
99
  "```"
94
100
  ].join("\n"),
95
- ExclusiveMaximum: [
96
- "**@ExclusiveMaximum** `<number>`",
101
+ exclusiveMaximum: [
102
+ "**@exclusiveMaximum** `<number>`",
97
103
  "",
98
104
  "Sets an exclusive upper bound on a numeric field.",
99
105
  "",
@@ -101,12 +107,25 @@ var CONSTRAINT_HOVER_DOCS = {
101
107
  "",
102
108
  "**Example:**",
103
109
  "```typescript",
104
- "/** @ExclusiveMaximum 1 */",
110
+ "/** @exclusiveMaximum 1 */",
105
111
  "ratio: number;",
106
112
  "```"
107
113
  ].join("\n"),
108
- MinLength: [
109
- "**@MinLength** `<number>`",
114
+ multipleOf: [
115
+ "**@multipleOf** `<number>`",
116
+ "",
117
+ "Requires the numeric value to be a multiple of the given number.",
118
+ "",
119
+ "Maps to `multipleOf` in JSON Schema.",
120
+ "",
121
+ "**Example:**",
122
+ "```typescript",
123
+ "/** @multipleOf 0.01 */",
124
+ "price: number;",
125
+ "```"
126
+ ].join("\n"),
127
+ minLength: [
128
+ "**@minLength** `<number>`",
110
129
  "",
111
130
  "Sets a minimum character length on a string field.",
112
131
  "",
@@ -114,12 +133,12 @@ var CONSTRAINT_HOVER_DOCS = {
114
133
  "",
115
134
  "**Example:**",
116
135
  "```typescript",
117
- "/** @MinLength 1 */",
136
+ "/** @minLength 1 */",
118
137
  "name: string;",
119
138
  "```"
120
139
  ].join("\n"),
121
- MaxLength: [
122
- "**@MaxLength** `<number>`",
140
+ maxLength: [
141
+ "**@maxLength** `<number>`",
123
142
  "",
124
143
  "Sets a maximum character length on a string field.",
125
144
  "",
@@ -127,12 +146,51 @@ var CONSTRAINT_HOVER_DOCS = {
127
146
  "",
128
147
  "**Example:**",
129
148
  "```typescript",
130
- "/** @MaxLength 255 */",
149
+ "/** @maxLength 255 */",
131
150
  "description: string;",
132
151
  "```"
133
152
  ].join("\n"),
134
- Pattern: [
135
- "**@Pattern** `<regex>`",
153
+ minItems: [
154
+ "**@minItems** `<number>`",
155
+ "",
156
+ "Sets a minimum number of items in an array field.",
157
+ "",
158
+ "Maps to `minItems` in JSON Schema.",
159
+ "",
160
+ "**Example:**",
161
+ "```typescript",
162
+ "/** @minItems 1 */",
163
+ "tags: string[];",
164
+ "```"
165
+ ].join("\n"),
166
+ maxItems: [
167
+ "**@maxItems** `<number>`",
168
+ "",
169
+ "Sets a maximum number of items in an array field.",
170
+ "",
171
+ "Maps to `maxItems` in JSON Schema.",
172
+ "",
173
+ "**Example:**",
174
+ "```typescript",
175
+ "/** @maxItems 10 */",
176
+ "tags: string[];",
177
+ "```"
178
+ ].join("\n"),
179
+ uniqueItems: [
180
+ "**@uniqueItems**",
181
+ "",
182
+ "Requires all items in an array field to be distinct.",
183
+ "",
184
+ "Maps to `uniqueItems` in JSON Schema.",
185
+ "",
186
+ "**Example:**",
187
+ "```typescript",
188
+ "/** @uniqueItems */",
189
+ "tags: string[];",
190
+ "```"
191
+ ].join("\n"),
192
+ pattern: [
193
+ "**@pattern** `<regex>`",
136
194
  "",
137
195
  "Sets a regular expression pattern that a string field must match.",
138
196
  "",
@@ -140,12 +198,12 @@ var CONSTRAINT_HOVER_DOCS = {
140
198
  "",
141
199
  "**Example:**",
142
200
  "```typescript",
143
- "/** @Pattern ^[a-z0-9]+$ */",
201
+ "/** @pattern ^[a-z0-9]+$ */",
144
202
  "slug: string;",
145
203
  "```"
146
204
  ].join("\n"),
147
- EnumOptions: [
148
- "**@EnumOptions** `<json-array>`",
205
+ enumOptions: [
206
+ "**@enumOptions** `<json-array>`",
149
207
  "",
150
208
  "Specifies the allowed values for an enum field as an inline JSON array.",
151
209
  "",
@@ -153,17 +211,28 @@ var CONSTRAINT_HOVER_DOCS = {
153
211
  "",
154
212
  "**Example:**",
155
213
  "```typescript",
156
- '/** @EnumOptions ["draft","sent","archived"] */',
214
+ '/** @enumOptions ["draft","sent","archived"] */',
157
215
  "status: string;",
158
216
  "```"
217
+ ].join("\n"),
218
+ const: [
219
+ "**@const** `<json-literal>`",
220
+ "",
221
+ "Requires the field value to equal a single constant JSON value.",
222
+ "",
223
+ "Maps to `const` in JSON Schema.",
224
+ "",
225
+ "**Example:**",
226
+ "```typescript",
227
+ '/** @const "USD" */',
228
+ "currency: string;",
229
+ "```"
159
230
  ].join("\n")
160
231
  };
161
- function isBuiltinConstraintName(name) {
162
- return Object.prototype.hasOwnProperty.call(import_core.BUILTIN_CONSTRAINT_DEFINITIONS, name);
163
- }
164
232
  function getHoverForTag(tagName) {
165
- const name = tagName.startsWith("@") ? tagName.slice(1) : tagName;
166
- if (!isBuiltinConstraintName(name)) {
233
+ const raw = tagName.startsWith("@") ? tagName.slice(1) : tagName;
234
+ const name = (0, import_core2.normalizeConstraintTagName)(raw);
235
+ if (!(0, import_core2.isBuiltinConstraintName)(name)) {
167
236
  return null;
168
237
  }
169
238
  return {
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/server.ts","../src/providers/completion.ts","../src/providers/hover.ts","../src/providers/definition.ts"],"sourcesContent":["/**\n * @formspec/language-server\n *\n * Language server for FormSpec — provides completions, hover documentation,\n * and go-to-definition for FormSpec JSDoc constraint tags (`@Minimum`,\n * `@Maximum`, `@Pattern`, etc.) in TypeScript files.\n *\n * This package implements the Language Server Protocol (LSP) using the\n * `vscode-languageserver` library. Constraint names are sourced from\n * `BUILTIN_CONSTRAINT_DEFINITIONS` in `@formspec/core`, ensuring the\n * language server stays in sync with the single source of truth.\n *\n * Diagnostics are intentionally omitted per design decision A7.\n *\n * @example\n * ```ts\n * import { createServer } from '@formspec/language-server';\n *\n * const connection = createServer();\n * connection.listen();\n * ```\n *\n * @packageDocumentation\n */\n\nexport { createServer } from \"./server.js\";\nexport { getCompletionItems } from \"./providers/completion.js\";\nexport { getHoverForTag } from \"./providers/hover.js\";\nexport { getDefinition } from \"./providers/definition.js\";\n","/**\n * FormSpec Language Server\n *\n * Sets up an LSP server connection and registers handlers for:\n * - `textDocument/completion` — FormSpec JSDoc constraint tag completions\n * - `textDocument/hover` — Documentation for recognized constraint tags\n * - `textDocument/definition` — Go-to-definition (stub, returns null)\n *\n * Diagnostics are intentionally omitted per design decision A7.\n */\n\nimport {\n createConnection,\n ProposedFeatures,\n TextDocumentSyncKind,\n type Connection,\n type InitializeResult,\n} from \"vscode-languageserver/node.js\";\nimport { getCompletionItems } from \"./providers/completion.js\";\nimport { getHoverForTag } from \"./providers/hover.js\";\nimport { getDefinition } from \"./providers/definition.js\";\n\n/**\n * Creates and configures the FormSpec language server connection.\n *\n * Registers LSP capability handlers and returns the connection.\n * Call `connection.listen()` to start accepting messages.\n *\n * @returns The configured LSP connection (not yet listening)\n */\nexport function createServer(): Connection {\n const connection = createConnection(ProposedFeatures.all);\n\n connection.onInitialize((): InitializeResult => {\n return {\n capabilities: {\n textDocumentSync: TextDocumentSyncKind.Incremental,\n completionProvider: {\n // Trigger completions inside JSDoc comments when `@` is typed\n triggerCharacters: [\"@\"],\n },\n hoverProvider: true,\n definitionProvider: true,\n },\n serverInfo: {\n name: \"formspec-language-server\",\n version: \"0.1.0\",\n },\n };\n });\n\n connection.onCompletion(() => {\n // Return all FormSpec constraint tag completions.\n // Future phases will add context-aware filtering based on field type and\n // cursor position within JSDoc comment ranges.\n return getCompletionItems();\n });\n\n connection.onHover((_params) => {\n // Extract the word under the cursor and look up hover documentation.\n // This is a stub — precise JSDoc token detection (checking that the\n // cursor is within a JSDoc comment and extracting the tag name) will be\n // added in a future phase.\n //\n // For now we return null to signal no hover is available until the\n // token extraction is implemented.\n return getHoverForTag(\"\");\n });\n\n connection.onDefinition((_params) => {\n // Go-to-definition is not yet implemented.\n return getDefinition();\n });\n\n return connection;\n}\n","/**\n * Completion provider for FormSpec JSDoc constraint tags.\n *\n * Returns completion items for all recognized FormSpec JSDoc constraint tags\n * (e.g., `@Minimum`, `@Maximum`, `@Pattern`), derived from\n * `BUILTIN_CONSTRAINT_DEFINITIONS`. This is a skeleton — context-aware\n * filtering will be added in a future phase.\n */\n\nimport { CompletionItem, CompletionItemKind } from \"vscode-languageserver/node.js\";\n\n/**\n * Human-readable detail strings for each built-in constraint tag.\n *\n * Keys match the constraint name (matching keys in `BUILTIN_CONSTRAINT_DEFINITIONS`).\n * Values are shown as the detail string in completion items.\n */\nconst CONSTRAINT_DETAIL: Record<string, string> = {\n Minimum: \"Minimum numeric value (inclusive). Example: `@Minimum 0`\",\n Maximum: \"Maximum numeric value (inclusive). Example: `@Maximum 100`\",\n ExclusiveMinimum: \"Minimum numeric value (exclusive). Example: `@ExclusiveMinimum 0`\",\n ExclusiveMaximum: \"Maximum numeric value (exclusive). Example: `@ExclusiveMaximum 100`\",\n MinLength: \"Minimum string length. Example: `@MinLength 1`\",\n MaxLength: \"Maximum string length. Example: `@MaxLength 255`\",\n Pattern: \"Regular expression pattern for string validation. Example: `@Pattern ^[a-z]+$`\",\n EnumOptions: 'Inline JSON array of allowed enum values. Example: `@EnumOptions [\"a\",\"b\",\"c\"]`',\n};\n\n/**\n * Returns completion items for all FormSpec JSDoc constraint tags.\n *\n * Items are derived from `BUILTIN_CONSTRAINT_DEFINITIONS`, ensuring this list\n * stays in sync with the single source of truth in `@formspec/core`.\n *\n * Each item uses `CompletionItemKind.Keyword` since these are annotation\n * tags used within JSDoc comments rather than language symbols.\n *\n * @returns An array of LSP completion items for FormSpec constraint tags\n */\nexport function getCompletionItems(): CompletionItem[] {\n return Object.entries(CONSTRAINT_DETAIL).map(([name, detail]) => ({\n\n label: `@${name}`,\n kind: CompletionItemKind.Keyword,\n detail,\n }));\n}\n","/**\n * Hover provider for FormSpec JSDoc constraint tags.\n *\n * Returns Markdown documentation for a recognized FormSpec JSDoc tag when\n * the cursor is positioned over it. This is a skeleton — precise token\n * detection within JSDoc comment ranges will be added in a future phase.\n */\n\nimport { BUILTIN_CONSTRAINT_DEFINITIONS, type BuiltinConstraintName } from \"@formspec/core\";\nimport type { Hover } from \"vscode-languageserver/node.js\";\n\n/**\n * Markdown documentation for each built-in FormSpec constraint tag.\n *\n * Keys are the canonical constraint names from `BUILTIN_CONSTRAINT_DEFINITIONS`.\n * Values are Markdown strings suitable for LSP hover responses.\n */\nconst CONSTRAINT_HOVER_DOCS: Record<BuiltinConstraintName, string> = {\n Minimum: [\n \"**@Minimum** `<number>`\",\n \"\",\n \"Sets an inclusive lower bound on a numeric field.\",\n \"\",\n \"Maps to `minimum` in JSON Schema.\",\n \"\",\n \"**Example:**\",\n \"```typescript\",\n \"/** @Minimum 0 */\",\n \"amount: number;\",\n \"```\",\n ].join(\"\\n\"),\n\n Maximum: [\n \"**@Maximum** `<number>`\",\n \"\",\n \"Sets an inclusive upper bound on a numeric field.\",\n \"\",\n \"Maps to `maximum` in JSON Schema.\",\n \"\",\n \"**Example:**\",\n \"```typescript\",\n \"/** @Maximum 100 */\",\n \"percentage: number;\",\n \"```\",\n ].join(\"\\n\"),\n\n ExclusiveMinimum: [\n \"**@ExclusiveMinimum** `<number>`\",\n \"\",\n \"Sets an exclusive lower bound on a numeric field.\",\n \"\",\n \"Maps to `exclusiveMinimum` in JSON Schema.\",\n \"\",\n \"**Example:**\",\n \"```typescript\",\n \"/** @ExclusiveMinimum 0 */\",\n \"positiveAmount: number;\",\n \"```\",\n ].join(\"\\n\"),\n\n ExclusiveMaximum: [\n \"**@ExclusiveMaximum** `<number>`\",\n \"\",\n \"Sets an exclusive upper bound on a numeric field.\",\n \"\",\n \"Maps to `exclusiveMaximum` in JSON Schema.\",\n \"\",\n \"**Example:**\",\n \"```typescript\",\n \"/** @ExclusiveMaximum 1 */\",\n \"ratio: number;\",\n \"```\",\n ].join(\"\\n\"),\n\n MinLength: [\n \"**@MinLength** `<number>`\",\n \"\",\n \"Sets a minimum character length on a string field.\",\n \"\",\n \"Maps to `minLength` in JSON Schema.\",\n \"\",\n \"**Example:**\",\n \"```typescript\",\n \"/** @MinLength 1 */\",\n \"name: string;\",\n \"```\",\n ].join(\"\\n\"),\n\n MaxLength: [\n \"**@MaxLength** `<number>`\",\n \"\",\n \"Sets a maximum character length on a string field.\",\n \"\",\n \"Maps to `maxLength` in JSON Schema.\",\n \"\",\n \"**Example:**\",\n \"```typescript\",\n \"/** @MaxLength 255 */\",\n \"description: string;\",\n \"```\",\n ].join(\"\\n\"),\n\n Pattern: [\n \"**@Pattern** `<regex>`\",\n \"\",\n \"Sets a regular expression pattern that a string field must match.\",\n \"\",\n \"Maps to `pattern` in JSON Schema.\",\n \"\",\n \"**Example:**\",\n \"```typescript\",\n \"/** @Pattern ^[a-z0-9]+$ */\",\n \"slug: string;\",\n \"```\",\n ].join(\"\\n\"),\n\n EnumOptions: [\n \"**@EnumOptions** `<json-array>`\",\n \"\",\n \"Specifies the allowed values for an enum field as an inline JSON array.\",\n \"\",\n \"Maps to `enum` in JSON Schema.\",\n \"\",\n \"**Example:**\",\n \"```typescript\",\n '/** @EnumOptions [\"draft\",\"sent\",\"archived\"] */',\n \"status: string;\",\n \"```\",\n ].join(\"\\n\"),\n} satisfies Record<BuiltinConstraintName, string>;\n\n/**\n * Checks whether a given string is a recognized built-in constraint name.\n *\n * @param name - The name to check\n * @returns `true` if `name` is a `BuiltinConstraintName`\n */\nfunction isBuiltinConstraintName(name: string): name is BuiltinConstraintName {\n return Object.prototype.hasOwnProperty.call(BUILTIN_CONSTRAINT_DEFINITIONS, name);\n}\n\n/**\n * Returns hover documentation for a FormSpec JSDoc tag name.\n *\n * The tag name lookup is case-sensitive and matches the canonical casing used\n * in `BUILTIN_CONSTRAINT_DEFINITIONS` (e.g., `\"Minimum\"`, `\"Pattern\"`).\n * The `@` prefix is stripped before lookup if present.\n * Returns `null` when the tag is not a recognized FormSpec constraint tag.\n *\n * @param tagName - The tag name to look up (e.g., `\"Minimum\"`, `\"@Pattern\"`)\n * @returns An LSP `Hover` response, or `null` if the tag is not recognized\n */\nexport function getHoverForTag(tagName: string): Hover | null {\n // Strip leading `@` prefix if present\n const name = tagName.startsWith(\"@\") ? tagName.slice(1) : tagName;\n\n if (!isBuiltinConstraintName(name)) {\n return null;\n }\n\n return {\n contents: {\n kind: \"markdown\",\n value: CONSTRAINT_HOVER_DOCS[name],\n },\n };\n}\n","/**\n * Go-to-definition provider for FormSpec.\n *\n * This is a stub — go-to-definition support (e.g., navigating from a\n * `field.text(\"name\")` call to the form definition that references it) will\n * be implemented in a future phase.\n */\n\nimport type { Location } from \"vscode-languageserver/node.js\";\n\n/**\n * Returns the definition location for a symbol at the given position.\n *\n * Always returns `null` in this stub implementation.\n *\n * @returns `null` — not yet implemented\n */\nexport function getDefinition(): Location | null {\n return null;\n}\n"],"mappings":"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","names":["import_node"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/server.ts","../src/providers/completion.ts","../src/providers/hover.ts","../src/providers/definition.ts"],"sourcesContent":["/**\n * \\@formspec/language-server\n *\n * Language server for FormSpec — provides completions, hover documentation,\n * and go-to-definition for FormSpec JSDoc constraint tags (`@Minimum`,\n * `@Maximum`, `@Pattern`, etc.) in TypeScript files.\n *\n * This package implements the Language Server Protocol (LSP) using the\n * `vscode-languageserver` library. Constraint names are sourced from\n * `BUILTIN_CONSTRAINT_DEFINITIONS` in `@formspec/core`, ensuring the\n * language server stays in sync with the single source of truth.\n *\n * Diagnostics are intentionally omitted per design decision A7.\n *\n * @example\n * ```ts\n * import { createServer } from '@formspec/language-server';\n *\n * const connection = createServer();\n * connection.listen();\n * ```\n *\n * @packageDocumentation\n */\n\nexport { createServer } from \"./server.js\";\nexport { getCompletionItems } from \"./providers/completion.js\";\nexport { getHoverForTag } from \"./providers/hover.js\";\nexport { getDefinition } from \"./providers/definition.js\";\n","/**\n * FormSpec Language Server\n *\n * Sets up an LSP server connection and registers handlers for:\n * - `textDocument/completion` — FormSpec JSDoc constraint tag completions\n * - `textDocument/hover` — Documentation for recognized constraint tags\n * - `textDocument/definition` — Go-to-definition (stub, returns null)\n *\n * Diagnostics are intentionally omitted per design decision A7.\n */\n\nimport {\n createConnection,\n ProposedFeatures,\n TextDocumentSyncKind,\n type Connection,\n type InitializeResult,\n} from \"vscode-languageserver/node.js\";\nimport { getCompletionItems } from \"./providers/completion.js\";\nimport { getHoverForTag } from \"./providers/hover.js\";\nimport { getDefinition } from \"./providers/definition.js\";\n\n/**\n * Creates and configures the FormSpec language server connection.\n *\n * Registers LSP capability handlers and returns the connection.\n * Call `connection.listen()` to start accepting messages.\n *\n * @returns The configured LSP connection (not yet listening)\n */\nexport function createServer(): Connection {\n const connection = createConnection(ProposedFeatures.all);\n\n connection.onInitialize((): InitializeResult => {\n return {\n capabilities: {\n textDocumentSync: TextDocumentSyncKind.Incremental,\n completionProvider: {\n // Trigger completions inside JSDoc comments when `@` is typed\n triggerCharacters: [\"@\"],\n },\n hoverProvider: true,\n definitionProvider: true,\n },\n serverInfo: {\n name: \"formspec-language-server\",\n version: \"0.1.0\",\n },\n };\n });\n\n connection.onCompletion(() => {\n // Return all FormSpec constraint tag completions.\n // Future phases will add context-aware filtering based on field type and\n // cursor position within JSDoc comment ranges.\n return getCompletionItems();\n });\n\n connection.onHover((_params) => {\n // Extract the word under the cursor and look up hover documentation.\n // This is a stub — precise JSDoc token detection (checking that the\n // cursor is within a JSDoc comment and extracting the tag name) will be\n // added in a future phase.\n //\n // For now we return null to signal no hover is available until the\n // token extraction is implemented.\n return getHoverForTag(\"\");\n });\n\n connection.onDefinition((_params) => {\n // Go-to-definition is not yet implemented.\n return getDefinition();\n });\n\n return connection;\n}\n","/**\n * Completion provider for FormSpec JSDoc constraint tags.\n *\n * Returns completion items for all recognized FormSpec JSDoc constraint tags\n * (e.g., `@minimum`, `@maximum`, `@pattern`), derived from\n * `BUILTIN_CONSTRAINT_DEFINITIONS`. This is a skeleton — context-aware\n * filtering will be added in a future phase.\n */\n\nimport { BUILTIN_CONSTRAINT_DEFINITIONS, type BuiltinConstraintName } from \"@formspec/core\";\nimport { CompletionItem, CompletionItemKind } from \"vscode-languageserver/node.js\";\n\n/**\n * Human-readable detail strings for each built-in constraint tag.\n *\n * Keys match the camelCase constraint names (matching keys in `BUILTIN_CONSTRAINT_DEFINITIONS`).\n * Values are shown as the detail string in completion items.\n */\nconst CONSTRAINT_DETAIL: Record<BuiltinConstraintName, string> = {\n minimum: \"Minimum numeric value (inclusive). Example: `@minimum 0`\",\n maximum: \"Maximum numeric value (inclusive). Example: `@maximum 100`\",\n exclusiveMinimum: \"Minimum numeric value (exclusive). Example: `@exclusiveMinimum 0`\",\n exclusiveMaximum: \"Maximum numeric value (exclusive). Example: `@exclusiveMaximum 100`\",\n multipleOf: \"Value must be a multiple of this number. Example: `@multipleOf 0.01`\",\n minLength: \"Minimum string length. Example: `@minLength 1`\",\n maxLength: \"Maximum string length. Example: `@maxLength 255`\",\n minItems: \"Minimum number of array items. Example: `@minItems 1`\",\n maxItems: \"Maximum number of array items. Example: `@maxItems 10`\",\n uniqueItems: \"Require all array items to be distinct. Example: `@uniqueItems`\",\n pattern: \"Regular expression pattern for string validation. Example: `@pattern ^[a-z]+$`\",\n enumOptions: 'Inline JSON array of allowed enum values. Example: `@enumOptions [\"a\",\"b\",\"c\"]`',\n const: 'Require a constant JSON value. Example: `@const \"USD\"`',\n};\n\n/**\n * Returns completion items for all FormSpec JSDoc constraint tags.\n *\n * Items are derived from `BUILTIN_CONSTRAINT_DEFINITIONS`, ensuring this list\n * stays in sync with the single source of truth in `@formspec/core`.\n *\n * Each item uses `CompletionItemKind.Keyword` since these are annotation\n * tags used within JSDoc comments rather than language symbols.\n *\n * @returns An array of LSP completion items for FormSpec constraint tags\n */\nexport function getCompletionItems(): CompletionItem[] {\n return (Object.keys(BUILTIN_CONSTRAINT_DEFINITIONS) as BuiltinConstraintName[]).map((name) => ({\n label: `@${name}`,\n kind: CompletionItemKind.Keyword,\n detail: CONSTRAINT_DETAIL[name],\n }));\n}\n","/**\n * Hover provider for FormSpec JSDoc constraint tags.\n *\n * Returns Markdown documentation for a recognized FormSpec JSDoc tag when\n * the cursor is positioned over it. This is a skeleton — precise token\n * detection within JSDoc comment ranges will be added in a future phase.\n */\n\nimport {\n normalizeConstraintTagName,\n isBuiltinConstraintName,\n type BuiltinConstraintName,\n} from \"@formspec/core\";\nimport type { Hover } from \"vscode-languageserver/node.js\";\n\n/**\n * Markdown documentation for each built-in FormSpec constraint tag.\n *\n * Keys are the canonical constraint names from `BUILTIN_CONSTRAINT_DEFINITIONS`.\n * Values are Markdown strings suitable for LSP hover responses.\n */\nconst CONSTRAINT_HOVER_DOCS: Record<BuiltinConstraintName, string> = {\n minimum: [\n \"**@minimum** `<number>`\",\n \"\",\n \"Sets an inclusive lower bound on a numeric field.\",\n \"\",\n \"Maps to `minimum` in JSON Schema.\",\n \"\",\n \"**Example:**\",\n \"```typescript\",\n \"/** @minimum 0 */\",\n \"amount: number;\",\n \"```\",\n ].join(\"\\n\"),\n\n maximum: [\n \"**@maximum** `<number>`\",\n \"\",\n \"Sets an inclusive upper bound on a numeric field.\",\n \"\",\n \"Maps to `maximum` in JSON Schema.\",\n \"\",\n \"**Example:**\",\n \"```typescript\",\n \"/** @maximum 100 */\",\n \"percentage: number;\",\n \"```\",\n ].join(\"\\n\"),\n\n exclusiveMinimum: [\n \"**@exclusiveMinimum** `<number>`\",\n \"\",\n \"Sets an exclusive lower bound on a numeric field.\",\n \"\",\n \"Maps to `exclusiveMinimum` in JSON Schema.\",\n \"\",\n \"**Example:**\",\n \"```typescript\",\n \"/** @exclusiveMinimum 0 */\",\n \"positiveAmount: number;\",\n \"```\",\n ].join(\"\\n\"),\n\n exclusiveMaximum: [\n \"**@exclusiveMaximum** `<number>`\",\n \"\",\n \"Sets an exclusive upper bound on a numeric field.\",\n \"\",\n \"Maps to `exclusiveMaximum` in JSON Schema.\",\n \"\",\n \"**Example:**\",\n \"```typescript\",\n \"/** @exclusiveMaximum 1 */\",\n \"ratio: number;\",\n \"```\",\n ].join(\"\\n\"),\n\n multipleOf: [\n \"**@multipleOf** `<number>`\",\n \"\",\n \"Requires the numeric value to be a multiple of the given number.\",\n \"\",\n \"Maps to `multipleOf` in JSON Schema.\",\n \"\",\n \"**Example:**\",\n \"```typescript\",\n \"/** @multipleOf 0.01 */\",\n \"price: number;\",\n \"```\",\n ].join(\"\\n\"),\n\n minLength: [\n \"**@minLength** `<number>`\",\n \"\",\n \"Sets a minimum character length on a string field.\",\n \"\",\n \"Maps to `minLength` in JSON Schema.\",\n \"\",\n \"**Example:**\",\n \"```typescript\",\n \"/** @minLength 1 */\",\n \"name: string;\",\n \"```\",\n ].join(\"\\n\"),\n\n maxLength: [\n \"**@maxLength** `<number>`\",\n \"\",\n \"Sets a maximum character length on a string field.\",\n \"\",\n \"Maps to `maxLength` in JSON Schema.\",\n \"\",\n \"**Example:**\",\n \"```typescript\",\n \"/** @maxLength 255 */\",\n \"description: string;\",\n \"```\",\n ].join(\"\\n\"),\n\n minItems: [\n \"**@minItems** `<number>`\",\n \"\",\n \"Sets a minimum number of items in an array field.\",\n \"\",\n \"Maps to `minItems` in JSON Schema.\",\n \"\",\n \"**Example:**\",\n \"```typescript\",\n \"/** @minItems 1 */\",\n \"tags: string[];\",\n \"```\",\n ].join(\"\\n\"),\n\n maxItems: [\n \"**@maxItems** `<number>`\",\n \"\",\n \"Sets a maximum number of items in an array field.\",\n \"\",\n \"Maps to `maxItems` in JSON Schema.\",\n \"\",\n \"**Example:**\",\n \"```typescript\",\n \"/** @maxItems 10 */\",\n \"tags: string[];\",\n \"```\",\n ].join(\"\\n\"),\n\n uniqueItems: [\n \"**@uniqueItems**\",\n \"\",\n \"Requires all items in an array field to be distinct.\",\n \"\",\n \"Maps to `uniqueItems` in JSON Schema.\",\n \"\",\n \"**Example:**\",\n \"```typescript\",\n \"/** @uniqueItems */\",\n \"tags: string[];\",\n \"```\",\n ].join(\"\\n\"),\n\n pattern: [\n \"**@pattern** `<regex>`\",\n \"\",\n \"Sets a regular expression pattern that a string field must match.\",\n \"\",\n \"Maps to `pattern` in JSON Schema.\",\n \"\",\n \"**Example:**\",\n \"```typescript\",\n \"/** @pattern ^[a-z0-9]+$ */\",\n \"slug: string;\",\n \"```\",\n ].join(\"\\n\"),\n\n enumOptions: [\n \"**@enumOptions** `<json-array>`\",\n \"\",\n \"Specifies the allowed values for an enum field as an inline JSON array.\",\n \"\",\n \"Maps to `enum` in JSON Schema.\",\n \"\",\n \"**Example:**\",\n \"```typescript\",\n '/** @enumOptions [\"draft\",\"sent\",\"archived\"] */',\n \"status: string;\",\n \"```\",\n ].join(\"\\n\"),\n\n const: [\n \"**@const** `<json-literal>`\",\n \"\",\n \"Requires the field value to equal a single constant JSON value.\",\n \"\",\n \"Maps to `const` in JSON Schema.\",\n \"\",\n \"**Example:**\",\n \"```typescript\",\n '/** @const \"USD\" */',\n \"currency: string;\",\n \"```\",\n ].join(\"\\n\"),\n} satisfies Record<BuiltinConstraintName, string>;\n\n/**\n * Returns hover documentation for a FormSpec JSDoc tag name.\n *\n * Accepts both camelCase (`\"minimum\"`) and PascalCase (`\"Minimum\"`) forms.\n * The `@` prefix is stripped before lookup if present.\n * Returns `null` when the tag is not a recognized FormSpec constraint tag.\n *\n * @param tagName - The tag name to look up (e.g., `\"minimum\"`, `\"@pattern\"`)\n * @returns An LSP `Hover` response, or `null` if the tag is not recognized\n */\nexport function getHoverForTag(tagName: string): Hover | null {\n // Strip leading `@` prefix if present\n const raw = tagName.startsWith(\"@\") ? tagName.slice(1) : tagName;\n const name = normalizeConstraintTagName(raw);\n\n if (!isBuiltinConstraintName(name)) {\n return null;\n }\n\n return {\n contents: {\n kind: \"markdown\",\n value: CONSTRAINT_HOVER_DOCS[name],\n },\n };\n}\n","/**\n * Go-to-definition provider for FormSpec.\n *\n * This is a stub — go-to-definition support (e.g., navigating from a\n * `field.text(\"name\")` call to the form definition that references it) will\n * be implemented in a future phase.\n */\n\nimport type { Location } from \"vscode-languageserver/node.js\";\n\n/**\n * Returns the definition location for a symbol at the given position.\n *\n * Always returns `null` in this stub implementation.\n *\n * @returns `null` — not yet implemented\n */\nexport function getDefinition(): Location | null {\n return null;\n}\n"],"mappings":"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","names":["import_node","import_core"]}
package/dist/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @formspec/language-server
2
+ * \@formspec/language-server
3
3
  *
4
4
  * Language server for FormSpec — provides completions, hover documentation,
5
5
  * and go-to-definition for FormSpec JSDoc constraint tags (`@Minimum`,
package/dist/index.js CHANGED
@@ -6,30 +6,39 @@ import {
6
6
  } from "vscode-languageserver/node.js";
7
7
 
8
8
  // src/providers/completion.ts
9
+ import { BUILTIN_CONSTRAINT_DEFINITIONS } from "@formspec/core";
9
10
  import { CompletionItemKind } from "vscode-languageserver/node.js";
10
11
  var CONSTRAINT_DETAIL = {
11
- Minimum: "Minimum numeric value (inclusive). Example: `@Minimum 0`",
12
- Maximum: "Maximum numeric value (inclusive). Example: `@Maximum 100`",
13
- ExclusiveMinimum: "Minimum numeric value (exclusive). Example: `@ExclusiveMinimum 0`",
14
- ExclusiveMaximum: "Maximum numeric value (exclusive). Example: `@ExclusiveMaximum 100`",
15
- MinLength: "Minimum string length. Example: `@MinLength 1`",
16
- MaxLength: "Maximum string length. Example: `@MaxLength 255`",
17
- Pattern: "Regular expression pattern for string validation. Example: `@Pattern ^[a-z]+$`",
18
- EnumOptions: 'Inline JSON array of allowed enum values. Example: `@EnumOptions ["a","b","c"]`'
12
+ minimum: "Minimum numeric value (inclusive). Example: `@minimum 0`",
13
+ maximum: "Maximum numeric value (inclusive). Example: `@maximum 100`",
14
+ exclusiveMinimum: "Minimum numeric value (exclusive). Example: `@exclusiveMinimum 0`",
15
+ exclusiveMaximum: "Maximum numeric value (exclusive). Example: `@exclusiveMaximum 100`",
16
+ multipleOf: "Value must be a multiple of this number. Example: `@multipleOf 0.01`",
17
+ minLength: "Minimum string length. Example: `@minLength 1`",
18
+ maxLength: "Maximum string length. Example: `@maxLength 255`",
19
+ minItems: "Minimum number of array items. Example: `@minItems 1`",
20
+ maxItems: "Maximum number of array items. Example: `@maxItems 10`",
21
+ uniqueItems: "Require all array items to be distinct. Example: `@uniqueItems`",
22
+ pattern: "Regular expression pattern for string validation. Example: `@pattern ^[a-z]+$`",
23
+ enumOptions: 'Inline JSON array of allowed enum values. Example: `@enumOptions ["a","b","c"]`',
24
+ const: 'Require a constant JSON value. Example: `@const "USD"`'
19
25
  };
20
26
  function getCompletionItems() {
21
- return Object.entries(CONSTRAINT_DETAIL).map(([name, detail]) => ({
27
+ return Object.keys(BUILTIN_CONSTRAINT_DEFINITIONS).map((name) => ({
22
28
  label: `@${name}`,
23
29
  kind: CompletionItemKind.Keyword,
24
- detail
30
+ detail: CONSTRAINT_DETAIL[name]
25
31
  }));
26
32
  }
27
33
 
28
34
  // src/providers/hover.ts
29
- import { BUILTIN_CONSTRAINT_DEFINITIONS } from "@formspec/core";
35
+ import {
36
+ normalizeConstraintTagName,
37
+ isBuiltinConstraintName
38
+ } from "@formspec/core";
30
39
  var CONSTRAINT_HOVER_DOCS = {
31
- Minimum: [
32
- "**@Minimum** `<number>`",
40
+ minimum: [
41
+ "**@minimum** `<number>`",
33
42
  "",
34
43
  "Sets an inclusive lower bound on a numeric field.",
35
44
  "",
@@ -37,12 +46,12 @@ var CONSTRAINT_HOVER_DOCS = {
37
46
  "",
38
47
  "**Example:**",
39
48
  "```typescript",
40
- "/** @Minimum 0 */",
49
+ "/** @minimum 0 */",
41
50
  "amount: number;",
42
51
  "```"
43
52
  ].join("\n"),
44
- Maximum: [
45
- "**@Maximum** `<number>`",
53
+ maximum: [
54
+ "**@maximum** `<number>`",
46
55
  "",
47
56
  "Sets an inclusive upper bound on a numeric field.",
48
57
  "",
@@ -50,12 +59,12 @@ var CONSTRAINT_HOVER_DOCS = {
50
59
  "",
51
60
  "**Example:**",
52
61
  "```typescript",
53
- "/** @Maximum 100 */",
62
+ "/** @maximum 100 */",
54
63
  "percentage: number;",
55
64
  "```"
56
65
  ].join("\n"),
57
- ExclusiveMinimum: [
58
- "**@ExclusiveMinimum** `<number>`",
66
+ exclusiveMinimum: [
67
+ "**@exclusiveMinimum** `<number>`",
59
68
  "",
60
69
  "Sets an exclusive lower bound on a numeric field.",
61
70
  "",
@@ -63,12 +72,12 @@ var CONSTRAINT_HOVER_DOCS = {
63
72
  "",
64
73
  "**Example:**",
65
74
  "```typescript",
66
- "/** @ExclusiveMinimum 0 */",
75
+ "/** @exclusiveMinimum 0 */",
67
76
  "positiveAmount: number;",
68
77
  "```"
69
78
  ].join("\n"),
70
- ExclusiveMaximum: [
71
- "**@ExclusiveMaximum** `<number>`",
79
+ exclusiveMaximum: [
80
+ "**@exclusiveMaximum** `<number>`",
72
81
  "",
73
82
  "Sets an exclusive upper bound on a numeric field.",
74
83
  "",
@@ -76,12 +85,25 @@ var CONSTRAINT_HOVER_DOCS = {
76
85
  "",
77
86
  "**Example:**",
78
87
  "```typescript",
79
- "/** @ExclusiveMaximum 1 */",
88
+ "/** @exclusiveMaximum 1 */",
80
89
  "ratio: number;",
81
90
  "```"
82
91
  ].join("\n"),
83
- MinLength: [
84
- "**@MinLength** `<number>`",
92
+ multipleOf: [
93
+ "**@multipleOf** `<number>`",
94
+ "",
95
+ "Requires the numeric value to be a multiple of the given number.",
96
+ "",
97
+ "Maps to `multipleOf` in JSON Schema.",
98
+ "",
99
+ "**Example:**",
100
+ "```typescript",
101
+ "/** @multipleOf 0.01 */",
102
+ "price: number;",
103
+ "```"
104
+ ].join("\n"),
105
+ minLength: [
106
+ "**@minLength** `<number>`",
85
107
  "",
86
108
  "Sets a minimum character length on a string field.",
87
109
  "",
@@ -89,12 +111,12 @@ var CONSTRAINT_HOVER_DOCS = {
89
111
  "",
90
112
  "**Example:**",
91
113
  "```typescript",
92
- "/** @MinLength 1 */",
114
+ "/** @minLength 1 */",
93
115
  "name: string;",
94
116
  "```"
95
117
  ].join("\n"),
96
- MaxLength: [
97
- "**@MaxLength** `<number>`",
118
+ maxLength: [
119
+ "**@maxLength** `<number>`",
98
120
  "",
99
121
  "Sets a maximum character length on a string field.",
100
122
  "",
@@ -102,12 +124,51 @@ var CONSTRAINT_HOVER_DOCS = {
102
124
  "",
103
125
  "**Example:**",
104
126
  "```typescript",
105
- "/** @MaxLength 255 */",
127
+ "/** @maxLength 255 */",
106
128
  "description: string;",
107
129
  "```"
108
130
  ].join("\n"),
109
- Pattern: [
110
- "**@Pattern** `<regex>`",
131
+ minItems: [
132
+ "**@minItems** `<number>`",
133
+ "",
134
+ "Sets a minimum number of items in an array field.",
135
+ "",
136
+ "Maps to `minItems` in JSON Schema.",
137
+ "",
138
+ "**Example:**",
139
+ "```typescript",
140
+ "/** @minItems 1 */",
141
+ "tags: string[];",
142
+ "```"
143
+ ].join("\n"),
144
+ maxItems: [
145
+ "**@maxItems** `<number>`",
146
+ "",
147
+ "Sets a maximum number of items in an array field.",
148
+ "",
149
+ "Maps to `maxItems` in JSON Schema.",
150
+ "",
151
+ "**Example:**",
152
+ "```typescript",
153
+ "/** @maxItems 10 */",
154
+ "tags: string[];",
155
+ "```"
156
+ ].join("\n"),
157
+ uniqueItems: [
158
+ "**@uniqueItems**",
159
+ "",
160
+ "Requires all items in an array field to be distinct.",
161
+ "",
162
+ "Maps to `uniqueItems` in JSON Schema.",
163
+ "",
164
+ "**Example:**",
165
+ "```typescript",
166
+ "/** @uniqueItems */",
167
+ "tags: string[];",
168
+ "```"
169
+ ].join("\n"),
170
+ pattern: [
171
+ "**@pattern** `<regex>`",
111
172
  "",
112
173
  "Sets a regular expression pattern that a string field must match.",
113
174
  "",
@@ -115,12 +176,12 @@ var CONSTRAINT_HOVER_DOCS = {
115
176
  "",
116
177
  "**Example:**",
117
178
  "```typescript",
118
- "/** @Pattern ^[a-z0-9]+$ */",
179
+ "/** @pattern ^[a-z0-9]+$ */",
119
180
  "slug: string;",
120
181
  "```"
121
182
  ].join("\n"),
122
- EnumOptions: [
123
- "**@EnumOptions** `<json-array>`",
183
+ enumOptions: [
184
+ "**@enumOptions** `<json-array>`",
124
185
  "",
125
186
  "Specifies the allowed values for an enum field as an inline JSON array.",
126
187
  "",
@@ -128,16 +189,27 @@ var CONSTRAINT_HOVER_DOCS = {
128
189
  "",
129
190
  "**Example:**",
130
191
  "```typescript",
131
- '/** @EnumOptions ["draft","sent","archived"] */',
192
+ '/** @enumOptions ["draft","sent","archived"] */',
132
193
  "status: string;",
133
194
  "```"
195
+ ].join("\n"),
196
+ const: [
197
+ "**@const** `<json-literal>`",
198
+ "",
199
+ "Requires the field value to equal a single constant JSON value.",
200
+ "",
201
+ "Maps to `const` in JSON Schema.",
202
+ "",
203
+ "**Example:**",
204
+ "```typescript",
205
+ '/** @const "USD" */',
206
+ "currency: string;",
207
+ "```"
134
208
  ].join("\n")
135
209
  };
136
- function isBuiltinConstraintName(name) {
137
- return Object.prototype.hasOwnProperty.call(BUILTIN_CONSTRAINT_DEFINITIONS, name);
138
- }
139
210
  function getHoverForTag(tagName) {
140
- const name = tagName.startsWith("@") ? tagName.slice(1) : tagName;
211
+ const raw = tagName.startsWith("@") ? tagName.slice(1) : tagName;
212
+ const name = normalizeConstraintTagName(raw);
141
213
  if (!isBuiltinConstraintName(name)) {
142
214
  return null;
143
215
  }
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/server.ts","../src/providers/completion.ts","../src/providers/hover.ts","../src/providers/definition.ts"],"sourcesContent":["/**\n * FormSpec Language Server\n *\n * Sets up an LSP server connection and registers handlers for:\n * - `textDocument/completion` — FormSpec JSDoc constraint tag completions\n * - `textDocument/hover` — Documentation for recognized constraint tags\n * - `textDocument/definition` — Go-to-definition (stub, returns null)\n *\n * Diagnostics are intentionally omitted per design decision A7.\n */\n\nimport {\n createConnection,\n ProposedFeatures,\n TextDocumentSyncKind,\n type Connection,\n type InitializeResult,\n} from \"vscode-languageserver/node.js\";\nimport { getCompletionItems } from \"./providers/completion.js\";\nimport { getHoverForTag } from \"./providers/hover.js\";\nimport { getDefinition } from \"./providers/definition.js\";\n\n/**\n * Creates and configures the FormSpec language server connection.\n *\n * Registers LSP capability handlers and returns the connection.\n * Call `connection.listen()` to start accepting messages.\n *\n * @returns The configured LSP connection (not yet listening)\n */\nexport function createServer(): Connection {\n const connection = createConnection(ProposedFeatures.all);\n\n connection.onInitialize((): InitializeResult => {\n return {\n capabilities: {\n textDocumentSync: TextDocumentSyncKind.Incremental,\n completionProvider: {\n // Trigger completions inside JSDoc comments when `@` is typed\n triggerCharacters: [\"@\"],\n },\n hoverProvider: true,\n definitionProvider: true,\n },\n serverInfo: {\n name: \"formspec-language-server\",\n version: \"0.1.0\",\n },\n };\n });\n\n connection.onCompletion(() => {\n // Return all FormSpec constraint tag completions.\n // Future phases will add context-aware filtering based on field type and\n // cursor position within JSDoc comment ranges.\n return getCompletionItems();\n });\n\n connection.onHover((_params) => {\n // Extract the word under the cursor and look up hover documentation.\n // This is a stub — precise JSDoc token detection (checking that the\n // cursor is within a JSDoc comment and extracting the tag name) will be\n // added in a future phase.\n //\n // For now we return null to signal no hover is available until the\n // token extraction is implemented.\n return getHoverForTag(\"\");\n });\n\n connection.onDefinition((_params) => {\n // Go-to-definition is not yet implemented.\n return getDefinition();\n });\n\n return connection;\n}\n","/**\n * Completion provider for FormSpec JSDoc constraint tags.\n *\n * Returns completion items for all recognized FormSpec JSDoc constraint tags\n * (e.g., `@Minimum`, `@Maximum`, `@Pattern`), derived from\n * `BUILTIN_CONSTRAINT_DEFINITIONS`. This is a skeleton — context-aware\n * filtering will be added in a future phase.\n */\n\nimport { CompletionItem, CompletionItemKind } from \"vscode-languageserver/node.js\";\n\n/**\n * Human-readable detail strings for each built-in constraint tag.\n *\n * Keys match the constraint name (matching keys in `BUILTIN_CONSTRAINT_DEFINITIONS`).\n * Values are shown as the detail string in completion items.\n */\nconst CONSTRAINT_DETAIL: Record<string, string> = {\n Minimum: \"Minimum numeric value (inclusive). Example: `@Minimum 0`\",\n Maximum: \"Maximum numeric value (inclusive). Example: `@Maximum 100`\",\n ExclusiveMinimum: \"Minimum numeric value (exclusive). Example: `@ExclusiveMinimum 0`\",\n ExclusiveMaximum: \"Maximum numeric value (exclusive). Example: `@ExclusiveMaximum 100`\",\n MinLength: \"Minimum string length. Example: `@MinLength 1`\",\n MaxLength: \"Maximum string length. Example: `@MaxLength 255`\",\n Pattern: \"Regular expression pattern for string validation. Example: `@Pattern ^[a-z]+$`\",\n EnumOptions: 'Inline JSON array of allowed enum values. Example: `@EnumOptions [\"a\",\"b\",\"c\"]`',\n};\n\n/**\n * Returns completion items for all FormSpec JSDoc constraint tags.\n *\n * Items are derived from `BUILTIN_CONSTRAINT_DEFINITIONS`, ensuring this list\n * stays in sync with the single source of truth in `@formspec/core`.\n *\n * Each item uses `CompletionItemKind.Keyword` since these are annotation\n * tags used within JSDoc comments rather than language symbols.\n *\n * @returns An array of LSP completion items for FormSpec constraint tags\n */\nexport function getCompletionItems(): CompletionItem[] {\n return Object.entries(CONSTRAINT_DETAIL).map(([name, detail]) => ({\n\n label: `@${name}`,\n kind: CompletionItemKind.Keyword,\n detail,\n }));\n}\n","/**\n * Hover provider for FormSpec JSDoc constraint tags.\n *\n * Returns Markdown documentation for a recognized FormSpec JSDoc tag when\n * the cursor is positioned over it. This is a skeleton — precise token\n * detection within JSDoc comment ranges will be added in a future phase.\n */\n\nimport { BUILTIN_CONSTRAINT_DEFINITIONS, type BuiltinConstraintName } from \"@formspec/core\";\nimport type { Hover } from \"vscode-languageserver/node.js\";\n\n/**\n * Markdown documentation for each built-in FormSpec constraint tag.\n *\n * Keys are the canonical constraint names from `BUILTIN_CONSTRAINT_DEFINITIONS`.\n * Values are Markdown strings suitable for LSP hover responses.\n */\nconst CONSTRAINT_HOVER_DOCS: Record<BuiltinConstraintName, string> = {\n Minimum: [\n \"**@Minimum** `<number>`\",\n \"\",\n \"Sets an inclusive lower bound on a numeric field.\",\n \"\",\n \"Maps to `minimum` in JSON Schema.\",\n \"\",\n \"**Example:**\",\n \"```typescript\",\n \"/** @Minimum 0 */\",\n \"amount: number;\",\n \"```\",\n ].join(\"\\n\"),\n\n Maximum: [\n \"**@Maximum** `<number>`\",\n \"\",\n \"Sets an inclusive upper bound on a numeric field.\",\n \"\",\n \"Maps to `maximum` in JSON Schema.\",\n \"\",\n \"**Example:**\",\n \"```typescript\",\n \"/** @Maximum 100 */\",\n \"percentage: number;\",\n \"```\",\n ].join(\"\\n\"),\n\n ExclusiveMinimum: [\n \"**@ExclusiveMinimum** `<number>`\",\n \"\",\n \"Sets an exclusive lower bound on a numeric field.\",\n \"\",\n \"Maps to `exclusiveMinimum` in JSON Schema.\",\n \"\",\n \"**Example:**\",\n \"```typescript\",\n \"/** @ExclusiveMinimum 0 */\",\n \"positiveAmount: number;\",\n \"```\",\n ].join(\"\\n\"),\n\n ExclusiveMaximum: [\n \"**@ExclusiveMaximum** `<number>`\",\n \"\",\n \"Sets an exclusive upper bound on a numeric field.\",\n \"\",\n \"Maps to `exclusiveMaximum` in JSON Schema.\",\n \"\",\n \"**Example:**\",\n \"```typescript\",\n \"/** @ExclusiveMaximum 1 */\",\n \"ratio: number;\",\n \"```\",\n ].join(\"\\n\"),\n\n MinLength: [\n \"**@MinLength** `<number>`\",\n \"\",\n \"Sets a minimum character length on a string field.\",\n \"\",\n \"Maps to `minLength` in JSON Schema.\",\n \"\",\n \"**Example:**\",\n \"```typescript\",\n \"/** @MinLength 1 */\",\n \"name: string;\",\n \"```\",\n ].join(\"\\n\"),\n\n MaxLength: [\n \"**@MaxLength** `<number>`\",\n \"\",\n \"Sets a maximum character length on a string field.\",\n \"\",\n \"Maps to `maxLength` in JSON Schema.\",\n \"\",\n \"**Example:**\",\n \"```typescript\",\n \"/** @MaxLength 255 */\",\n \"description: string;\",\n \"```\",\n ].join(\"\\n\"),\n\n Pattern: [\n \"**@Pattern** `<regex>`\",\n \"\",\n \"Sets a regular expression pattern that a string field must match.\",\n \"\",\n \"Maps to `pattern` in JSON Schema.\",\n \"\",\n \"**Example:**\",\n \"```typescript\",\n \"/** @Pattern ^[a-z0-9]+$ */\",\n \"slug: string;\",\n \"```\",\n ].join(\"\\n\"),\n\n EnumOptions: [\n \"**@EnumOptions** `<json-array>`\",\n \"\",\n \"Specifies the allowed values for an enum field as an inline JSON array.\",\n \"\",\n \"Maps to `enum` in JSON Schema.\",\n \"\",\n \"**Example:**\",\n \"```typescript\",\n '/** @EnumOptions [\"draft\",\"sent\",\"archived\"] */',\n \"status: string;\",\n \"```\",\n ].join(\"\\n\"),\n} satisfies Record<BuiltinConstraintName, string>;\n\n/**\n * Checks whether a given string is a recognized built-in constraint name.\n *\n * @param name - The name to check\n * @returns `true` if `name` is a `BuiltinConstraintName`\n */\nfunction isBuiltinConstraintName(name: string): name is BuiltinConstraintName {\n return Object.prototype.hasOwnProperty.call(BUILTIN_CONSTRAINT_DEFINITIONS, name);\n}\n\n/**\n * Returns hover documentation for a FormSpec JSDoc tag name.\n *\n * The tag name lookup is case-sensitive and matches the canonical casing used\n * in `BUILTIN_CONSTRAINT_DEFINITIONS` (e.g., `\"Minimum\"`, `\"Pattern\"`).\n * The `@` prefix is stripped before lookup if present.\n * Returns `null` when the tag is not a recognized FormSpec constraint tag.\n *\n * @param tagName - The tag name to look up (e.g., `\"Minimum\"`, `\"@Pattern\"`)\n * @returns An LSP `Hover` response, or `null` if the tag is not recognized\n */\nexport function getHoverForTag(tagName: string): Hover | null {\n // Strip leading `@` prefix if present\n const name = tagName.startsWith(\"@\") ? tagName.slice(1) : tagName;\n\n if (!isBuiltinConstraintName(name)) {\n return null;\n }\n\n return {\n contents: {\n kind: \"markdown\",\n value: CONSTRAINT_HOVER_DOCS[name],\n },\n };\n}\n","/**\n * Go-to-definition provider for FormSpec.\n *\n * This is a stub — go-to-definition support (e.g., navigating from a\n * `field.text(\"name\")` call to the form definition that references it) will\n * be implemented in a future phase.\n */\n\nimport type { Location } from \"vscode-languageserver/node.js\";\n\n/**\n * Returns the definition location for a symbol at the given position.\n *\n * Always returns `null` in this stub implementation.\n *\n * @returns `null` — not yet implemented\n */\nexport function getDefinition(): Location | null {\n return null;\n}\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/server.ts","../src/providers/completion.ts","../src/providers/hover.ts","../src/providers/definition.ts"],"sourcesContent":["/**\n * FormSpec Language Server\n *\n * Sets up an LSP server connection and registers handlers for:\n * - `textDocument/completion` — FormSpec JSDoc constraint tag completions\n * - `textDocument/hover` — Documentation for recognized constraint tags\n * - `textDocument/definition` — Go-to-definition (stub, returns null)\n *\n * Diagnostics are intentionally omitted per design decision A7.\n */\n\nimport {\n createConnection,\n ProposedFeatures,\n TextDocumentSyncKind,\n type Connection,\n type InitializeResult,\n} from \"vscode-languageserver/node.js\";\nimport { getCompletionItems } from \"./providers/completion.js\";\nimport { getHoverForTag } from \"./providers/hover.js\";\nimport { getDefinition } from \"./providers/definition.js\";\n\n/**\n * Creates and configures the FormSpec language server connection.\n *\n * Registers LSP capability handlers and returns the connection.\n * Call `connection.listen()` to start accepting messages.\n *\n * @returns The configured LSP connection (not yet listening)\n */\nexport function createServer(): Connection {\n const connection = createConnection(ProposedFeatures.all);\n\n connection.onInitialize((): InitializeResult => {\n return {\n capabilities: {\n textDocumentSync: TextDocumentSyncKind.Incremental,\n completionProvider: {\n // Trigger completions inside JSDoc comments when `@` is typed\n triggerCharacters: [\"@\"],\n },\n hoverProvider: true,\n definitionProvider: true,\n },\n serverInfo: {\n name: \"formspec-language-server\",\n version: \"0.1.0\",\n },\n };\n });\n\n connection.onCompletion(() => {\n // Return all FormSpec constraint tag completions.\n // Future phases will add context-aware filtering based on field type and\n // cursor position within JSDoc comment ranges.\n return getCompletionItems();\n });\n\n connection.onHover((_params) => {\n // Extract the word under the cursor and look up hover documentation.\n // This is a stub — precise JSDoc token detection (checking that the\n // cursor is within a JSDoc comment and extracting the tag name) will be\n // added in a future phase.\n //\n // For now we return null to signal no hover is available until the\n // token extraction is implemented.\n return getHoverForTag(\"\");\n });\n\n connection.onDefinition((_params) => {\n // Go-to-definition is not yet implemented.\n return getDefinition();\n });\n\n return connection;\n}\n","/**\n * Completion provider for FormSpec JSDoc constraint tags.\n *\n * Returns completion items for all recognized FormSpec JSDoc constraint tags\n * (e.g., `@minimum`, `@maximum`, `@pattern`), derived from\n * `BUILTIN_CONSTRAINT_DEFINITIONS`. This is a skeleton — context-aware\n * filtering will be added in a future phase.\n */\n\nimport { BUILTIN_CONSTRAINT_DEFINITIONS, type BuiltinConstraintName } from \"@formspec/core\";\nimport { CompletionItem, CompletionItemKind } from \"vscode-languageserver/node.js\";\n\n/**\n * Human-readable detail strings for each built-in constraint tag.\n *\n * Keys match the camelCase constraint names (matching keys in `BUILTIN_CONSTRAINT_DEFINITIONS`).\n * Values are shown as the detail string in completion items.\n */\nconst CONSTRAINT_DETAIL: Record<BuiltinConstraintName, string> = {\n minimum: \"Minimum numeric value (inclusive). Example: `@minimum 0`\",\n maximum: \"Maximum numeric value (inclusive). Example: `@maximum 100`\",\n exclusiveMinimum: \"Minimum numeric value (exclusive). Example: `@exclusiveMinimum 0`\",\n exclusiveMaximum: \"Maximum numeric value (exclusive). Example: `@exclusiveMaximum 100`\",\n multipleOf: \"Value must be a multiple of this number. Example: `@multipleOf 0.01`\",\n minLength: \"Minimum string length. Example: `@minLength 1`\",\n maxLength: \"Maximum string length. Example: `@maxLength 255`\",\n minItems: \"Minimum number of array items. Example: `@minItems 1`\",\n maxItems: \"Maximum number of array items. Example: `@maxItems 10`\",\n uniqueItems: \"Require all array items to be distinct. Example: `@uniqueItems`\",\n pattern: \"Regular expression pattern for string validation. Example: `@pattern ^[a-z]+$`\",\n enumOptions: 'Inline JSON array of allowed enum values. Example: `@enumOptions [\"a\",\"b\",\"c\"]`',\n const: 'Require a constant JSON value. Example: `@const \"USD\"`',\n};\n\n/**\n * Returns completion items for all FormSpec JSDoc constraint tags.\n *\n * Items are derived from `BUILTIN_CONSTRAINT_DEFINITIONS`, ensuring this list\n * stays in sync with the single source of truth in `@formspec/core`.\n *\n * Each item uses `CompletionItemKind.Keyword` since these are annotation\n * tags used within JSDoc comments rather than language symbols.\n *\n * @returns An array of LSP completion items for FormSpec constraint tags\n */\nexport function getCompletionItems(): CompletionItem[] {\n return (Object.keys(BUILTIN_CONSTRAINT_DEFINITIONS) as BuiltinConstraintName[]).map((name) => ({\n label: `@${name}`,\n kind: CompletionItemKind.Keyword,\n detail: CONSTRAINT_DETAIL[name],\n }));\n}\n","/**\n * Hover provider for FormSpec JSDoc constraint tags.\n *\n * Returns Markdown documentation for a recognized FormSpec JSDoc tag when\n * the cursor is positioned over it. This is a skeleton — precise token\n * detection within JSDoc comment ranges will be added in a future phase.\n */\n\nimport {\n normalizeConstraintTagName,\n isBuiltinConstraintName,\n type BuiltinConstraintName,\n} from \"@formspec/core\";\nimport type { Hover } from \"vscode-languageserver/node.js\";\n\n/**\n * Markdown documentation for each built-in FormSpec constraint tag.\n *\n * Keys are the canonical constraint names from `BUILTIN_CONSTRAINT_DEFINITIONS`.\n * Values are Markdown strings suitable for LSP hover responses.\n */\nconst CONSTRAINT_HOVER_DOCS: Record<BuiltinConstraintName, string> = {\n minimum: [\n \"**@minimum** `<number>`\",\n \"\",\n \"Sets an inclusive lower bound on a numeric field.\",\n \"\",\n \"Maps to `minimum` in JSON Schema.\",\n \"\",\n \"**Example:**\",\n \"```typescript\",\n \"/** @minimum 0 */\",\n \"amount: number;\",\n \"```\",\n ].join(\"\\n\"),\n\n maximum: [\n \"**@maximum** `<number>`\",\n \"\",\n \"Sets an inclusive upper bound on a numeric field.\",\n \"\",\n \"Maps to `maximum` in JSON Schema.\",\n \"\",\n \"**Example:**\",\n \"```typescript\",\n \"/** @maximum 100 */\",\n \"percentage: number;\",\n \"```\",\n ].join(\"\\n\"),\n\n exclusiveMinimum: [\n \"**@exclusiveMinimum** `<number>`\",\n \"\",\n \"Sets an exclusive lower bound on a numeric field.\",\n \"\",\n \"Maps to `exclusiveMinimum` in JSON Schema.\",\n \"\",\n \"**Example:**\",\n \"```typescript\",\n \"/** @exclusiveMinimum 0 */\",\n \"positiveAmount: number;\",\n \"```\",\n ].join(\"\\n\"),\n\n exclusiveMaximum: [\n \"**@exclusiveMaximum** `<number>`\",\n \"\",\n \"Sets an exclusive upper bound on a numeric field.\",\n \"\",\n \"Maps to `exclusiveMaximum` in JSON Schema.\",\n \"\",\n \"**Example:**\",\n \"```typescript\",\n \"/** @exclusiveMaximum 1 */\",\n \"ratio: number;\",\n \"```\",\n ].join(\"\\n\"),\n\n multipleOf: [\n \"**@multipleOf** `<number>`\",\n \"\",\n \"Requires the numeric value to be a multiple of the given number.\",\n \"\",\n \"Maps to `multipleOf` in JSON Schema.\",\n \"\",\n \"**Example:**\",\n \"```typescript\",\n \"/** @multipleOf 0.01 */\",\n \"price: number;\",\n \"```\",\n ].join(\"\\n\"),\n\n minLength: [\n \"**@minLength** `<number>`\",\n \"\",\n \"Sets a minimum character length on a string field.\",\n \"\",\n \"Maps to `minLength` in JSON Schema.\",\n \"\",\n \"**Example:**\",\n \"```typescript\",\n \"/** @minLength 1 */\",\n \"name: string;\",\n \"```\",\n ].join(\"\\n\"),\n\n maxLength: [\n \"**@maxLength** `<number>`\",\n \"\",\n \"Sets a maximum character length on a string field.\",\n \"\",\n \"Maps to `maxLength` in JSON Schema.\",\n \"\",\n \"**Example:**\",\n \"```typescript\",\n \"/** @maxLength 255 */\",\n \"description: string;\",\n \"```\",\n ].join(\"\\n\"),\n\n minItems: [\n \"**@minItems** `<number>`\",\n \"\",\n \"Sets a minimum number of items in an array field.\",\n \"\",\n \"Maps to `minItems` in JSON Schema.\",\n \"\",\n \"**Example:**\",\n \"```typescript\",\n \"/** @minItems 1 */\",\n \"tags: string[];\",\n \"```\",\n ].join(\"\\n\"),\n\n maxItems: [\n \"**@maxItems** `<number>`\",\n \"\",\n \"Sets a maximum number of items in an array field.\",\n \"\",\n \"Maps to `maxItems` in JSON Schema.\",\n \"\",\n \"**Example:**\",\n \"```typescript\",\n \"/** @maxItems 10 */\",\n \"tags: string[];\",\n \"```\",\n ].join(\"\\n\"),\n\n uniqueItems: [\n \"**@uniqueItems**\",\n \"\",\n \"Requires all items in an array field to be distinct.\",\n \"\",\n \"Maps to `uniqueItems` in JSON Schema.\",\n \"\",\n \"**Example:**\",\n \"```typescript\",\n \"/** @uniqueItems */\",\n \"tags: string[];\",\n \"```\",\n ].join(\"\\n\"),\n\n pattern: [\n \"**@pattern** `<regex>`\",\n \"\",\n \"Sets a regular expression pattern that a string field must match.\",\n \"\",\n \"Maps to `pattern` in JSON Schema.\",\n \"\",\n \"**Example:**\",\n \"```typescript\",\n \"/** @pattern ^[a-z0-9]+$ */\",\n \"slug: string;\",\n \"```\",\n ].join(\"\\n\"),\n\n enumOptions: [\n \"**@enumOptions** `<json-array>`\",\n \"\",\n \"Specifies the allowed values for an enum field as an inline JSON array.\",\n \"\",\n \"Maps to `enum` in JSON Schema.\",\n \"\",\n \"**Example:**\",\n \"```typescript\",\n '/** @enumOptions [\"draft\",\"sent\",\"archived\"] */',\n \"status: string;\",\n \"```\",\n ].join(\"\\n\"),\n\n const: [\n \"**@const** `<json-literal>`\",\n \"\",\n \"Requires the field value to equal a single constant JSON value.\",\n \"\",\n \"Maps to `const` in JSON Schema.\",\n \"\",\n \"**Example:**\",\n \"```typescript\",\n '/** @const \"USD\" */',\n \"currency: string;\",\n \"```\",\n ].join(\"\\n\"),\n} satisfies Record<BuiltinConstraintName, string>;\n\n/**\n * Returns hover documentation for a FormSpec JSDoc tag name.\n *\n * Accepts both camelCase (`\"minimum\"`) and PascalCase (`\"Minimum\"`) forms.\n * The `@` prefix is stripped before lookup if present.\n * Returns `null` when the tag is not a recognized FormSpec constraint tag.\n *\n * @param tagName - The tag name to look up (e.g., `\"minimum\"`, `\"@pattern\"`)\n * @returns An LSP `Hover` response, or `null` if the tag is not recognized\n */\nexport function getHoverForTag(tagName: string): Hover | null {\n // Strip leading `@` prefix if present\n const raw = tagName.startsWith(\"@\") ? tagName.slice(1) : tagName;\n const name = normalizeConstraintTagName(raw);\n\n if (!isBuiltinConstraintName(name)) {\n return null;\n }\n\n return {\n contents: {\n kind: \"markdown\",\n value: CONSTRAINT_HOVER_DOCS[name],\n },\n };\n}\n","/**\n * Go-to-definition provider for FormSpec.\n *\n * This is a stub — go-to-definition support (e.g., navigating from a\n * `field.text(\"name\")` call to the form definition that references it) will\n * be implemented in a future phase.\n */\n\nimport type { Location } from \"vscode-languageserver/node.js\";\n\n/**\n * Returns the definition location for a symbol at the given position.\n *\n * Always returns `null` in this stub implementation.\n *\n * @returns `null` — not yet implemented\n */\nexport function getDefinition(): Location | null {\n return null;\n}\n"],"mappings":"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","names":[]}
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @formspec/language-server
2
+ * \@formspec/language-server
3
3
  *
4
4
  * Language server for FormSpec — provides completions, hover documentation,
5
5
  * and go-to-definition for FormSpec JSDoc constraint tags (`@Minimum`,
@@ -63,12 +63,11 @@ export declare function getDefinition(): Location | null;
63
63
  /**
64
64
  * Returns hover documentation for a FormSpec JSDoc tag name.
65
65
  *
66
- * The tag name lookup is case-sensitive and matches the canonical casing used
67
- * in `BUILTIN_CONSTRAINT_DEFINITIONS` (e.g., `"Minimum"`, `"Pattern"`).
66
+ * Accepts both camelCase (`"minimum"`) and PascalCase (`"Minimum"`) forms.
68
67
  * The `@` prefix is stripped before lookup if present.
69
68
  * Returns `null` when the tag is not a recognized FormSpec constraint tag.
70
69
  *
71
- * @param tagName - The tag name to look up (e.g., `"Minimum"`, `"@Pattern"`)
70
+ * @param tagName - The tag name to look up (e.g., `"minimum"`, `"@pattern"`)
72
71
  * @returns An LSP `Hover` response, or `null` if the tag is not recognized
73
72
  */
74
73
  export declare function getHoverForTag(tagName: string): Hover | null;
@@ -2,7 +2,7 @@
2
2
  * Completion provider for FormSpec JSDoc constraint tags.
3
3
  *
4
4
  * Returns completion items for all recognized FormSpec JSDoc constraint tags
5
- * (e.g., `@Minimum`, `@Maximum`, `@Pattern`), derived from
5
+ * (e.g., `@minimum`, `@maximum`, `@pattern`), derived from
6
6
  * `BUILTIN_CONSTRAINT_DEFINITIONS`. This is a skeleton — context-aware
7
7
  * filtering will be added in a future phase.
8
8
  */
@@ -1 +1 @@
1
- {"version":3,"file":"completion.d.ts","sourceRoot":"","sources":["../../src/providers/completion.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,OAAO,EAAE,cAAc,EAAsB,MAAM,+BAA+B,CAAC;AAmBnF;;;;;;;;;;GAUG;AACH,wBAAgB,kBAAkB,IAAI,cAAc,EAAE,CAOrD"}
1
+ {"version":3,"file":"completion.d.ts","sourceRoot":"","sources":["../../src/providers/completion.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,EAAE,cAAc,EAAsB,MAAM,+BAA+B,CAAC;AAwBnF;;;;;;;;;;GAUG;AACH,wBAAgB,kBAAkB,IAAI,cAAc,EAAE,CAMrD"}
@@ -9,12 +9,11 @@ import type { Hover } from "vscode-languageserver/node.js";
9
9
  /**
10
10
  * Returns hover documentation for a FormSpec JSDoc tag name.
11
11
  *
12
- * The tag name lookup is case-sensitive and matches the canonical casing used
13
- * in `BUILTIN_CONSTRAINT_DEFINITIONS` (e.g., `"Minimum"`, `"Pattern"`).
12
+ * Accepts both camelCase (`"minimum"`) and PascalCase (`"Minimum"`) forms.
14
13
  * The `@` prefix is stripped before lookup if present.
15
14
  * Returns `null` when the tag is not a recognized FormSpec constraint tag.
16
15
  *
17
- * @param tagName - The tag name to look up (e.g., `"Minimum"`, `"@Pattern"`)
16
+ * @param tagName - The tag name to look up (e.g., `"minimum"`, `"@pattern"`)
18
17
  * @returns An LSP `Hover` response, or `null` if the tag is not recognized
19
18
  */
20
19
  export declare function getHoverForTag(tagName: string): Hover | null;
@@ -1 +1 @@
1
- {"version":3,"file":"hover.d.ts","sourceRoot":"","sources":["../../src/providers/hover.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAGH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,+BAA+B,CAAC;AAoI3D;;;;;;;;;;GAUG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,KAAK,GAAG,IAAI,CAc5D"}
1
+ {"version":3,"file":"hover.d.ts","sourceRoot":"","sources":["../../src/providers/hover.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAOH,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,+BAA+B,CAAC;AAgM3D;;;;;;;;;GASG;AACH,wBAAgB,cAAc,CAAC,OAAO,EAAE,MAAM,GAAG,KAAK,GAAG,IAAI,CAe5D"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@formspec/language-server",
3
- "version": "0.1.0-alpha.13",
3
+ "version": "0.1.0-alpha.16",
4
4
  "description": "Language server for FormSpec — completions, hover, and go-to-definition for JSDoc constraint tags",
5
5
  "type": "module",
6
6
  "main": "./dist/index.cjs",
@@ -20,7 +20,7 @@
20
20
  "dependencies": {
21
21
  "vscode-languageserver": "^9.0.1",
22
22
  "vscode-languageserver-textdocument": "^1.0.12",
23
- "@formspec/core": "0.1.0-alpha.13"
23
+ "@formspec/core": "0.1.0-alpha.16"
24
24
  },
25
25
  "devDependencies": {
26
26
  "vitest": "^3.0.0"