rlsp-yaml 0.6.0

A fast, lightweight YAML language server
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
# Configuration

rlsp-yaml is configured through three mechanisms, listed from highest to lowest priority:

1. **Modelines** — per-document comments that override workspace settings
2. **Workspace settings** — passed via `initializationOptions` or `workspace/didChangeConfiguration`
3. **Defaults** — sensible built-in defaults when no configuration is provided

## Workspace Settings

Settings are passed as a JSON object via LSP `initializationOptions` at startup or `workspace/didChangeConfiguration` at runtime. Each update replaces the entire settings object.

```json
{
  "customTags": ["!include", "!ref"],
  "keyOrdering": false,
  "kubernetesVersion": "master",
  "schemaStore": true,
  "formatValidation": true,
  "formatPrintWidth": 80,
  "formatSingleQuote": false,
  "yamlVersion": "1.2",
  "httpProxy": "http://proxy.corp:8080",
  "validate": true,
  "hover": true,
  "completion": true,
  "maxItemsComputed": 5000,
  "schemas": {
    "https://json.schemastore.org/github-workflow": ".github/workflows/*.yml",
    "https://example.com/schema.json": "deploy/**/*.yaml"
  }
}
```

### `customTags`

- **Type:** `string[]`
- **Default:** `[]` (empty — custom tag validation disabled)

A list of allowed YAML custom tag names. When non-empty, documents are validated against this list and unknown tags produce diagnostics.

Tags from the workspace setting are merged with any tags declared via modeline (see below).

### `keyOrdering`

- **Type:** `boolean`
- **Default:** `false`

When enabled, the server warns if mapping keys are not in alphabetical order.

### `kubernetesVersion`

- **Type:** `string`
- **Default:** `"master"` (tracks the latest available schemas)

The Kubernetes cluster version used for automatic schema resolution. When a document contains root-level `apiVersion` and `kind` fields and no schema is configured via modeline or glob, the server fetches the corresponding schema from [yannh/kubernetes-json-schema](https://github.com/yannh/kubernetes-json-schema) using this version string.

Set this to match your cluster version to get accurate validation:

```json
{ "kubernetesVersion": "1.29.0" }
```

### `schemaStore`

- **Type:** `boolean`
- **Default:** `true`

Enable automatic schema association using the [SchemaStore](https://www.schemastore.org/) catalog. When enabled, the server fetches the SchemaStore catalog on first use and matches each YAML file's path against the catalog's `fileMatch` patterns. If a match is found, the corresponding schema is fetched and used for validation, completion, and hover.

This is the lowest-priority fallback — it only applies when no modeline, workspace glob, or Kubernetes auto-detection match is found for a file.

The catalog is fetched lazily (on first need) and cached in memory for the session. If the catalog fetch fails (e.g. no network), the server continues without SchemaStore and no diagnostics are lost.

To disable SchemaStore association:

```json
{ "schemaStore": false }
```

### `schemas`

- **Type:** `object` (schema URL → glob pattern)
- **Default:** `{}` (empty — no schema associations)

Maps JSON Schema URLs to file glob patterns. When a document's URI matches a pattern, the corresponding schema is fetched and used for validation, completion, and hover.

Glob syntax:
- `*` matches any characters except `/`
- `**` matches any characters including `/`

A modeline `$schema=` in the document takes priority over glob-based associations.

### `formatPrintWidth`

- **Type:** `number`
- **Default:** `80`

Maximum line width for the full-document formatter. The formatter tries to fit content on a single line up to this width; if it doesn't fit, it breaks to block style.

### `formatSingleQuote`

- **Type:** `boolean`
- **Default:** `false`

When `true`, string scalars are wrapped in single quotes instead of double quotes. Strings that contain single quotes are always double-quoted regardless of this setting.

### `yamlVersion`

- **Type:** `string` (optional)
- **Values:** `"1.1"` or `"1.2"`
- **Default:** `"1.2"`

Controls which YAML specification version the formatter uses for quoting decisions.

| Version | Keywords that require quoting |
|---------|-------------------------------|
| `"1.2"` | `true`, `false`, `null` (and case variants) |
| `"1.1"` | All of the above, plus `on`, `off`, `yes`, `no` (and case variants) |

In `"1.1"` mode the formatter quotes these words to prevent ambiguity — for example, `on: push` stays plain (it is a key, already in the AST as a plain scalar), but a value like `enabled: "yes"` will have its quotes preserved rather than stripped.

> **Parser limitation:** the underlying parser (rlsp-yaml-parser) always processes documents as YAML 1.2 regardless of this setting. Octal literals (`0644`) and sexagesimal values (`1:30:00`) are therefore treated as plain strings, not integers. This setting affects formatter quoting only.

Override this setting for a single document with the `$yamlVersion` modeline (see below).

```json
{ "yamlVersion": "1.1" }
```

### `formatValidation`

- **Type:** `boolean` (optional)
- **Default:** `true`

Enable validation of the JSON Schema `format` keyword, `contentEncoding`, and `contentMediaType` keywords. When enabled:

- String values are checked against the declared `format` and a **warning** diagnostic (`schemaFormat`) is emitted for values that do not conform.
- String values are decoded against the declared `contentEncoding` and a **warning** diagnostic (`schemaContentEncoding`) is emitted for values that cannot be decoded.
- Decoded content is checked against the declared `contentMediaType` and a **warning** diagnostic (`schemaContentMediaType`) is emitted for content that does not match.

When disabled, all three keyword checks are skipped (annotation-only mode, per Draft 2019-09+).

Supported `format` values:

| Format | Description |
|--------|-------------|
| `date-time` | RFC 3339 full date-time (e.g. `2023-01-15T10:30:00Z`) |
| `date` | RFC 3339 full date (e.g. `2023-01-15`) |
| `time` | RFC 3339 partial-time with offset (e.g. `10:30:00Z`) |
| `duration` | ISO 8601 duration (e.g. `P1Y2M3DT4H`) |
| `email` | Basic email address |
| `ipv4` | IPv4 dotted-quad address |
| `ipv6` | IPv6 address |
| `hostname` | RFC 1123 hostname |
| `uri` | URI with scheme |
| `uri-reference` | URI or relative reference |
| `uri-template` | RFC 6570 URI template |
| `uuid` | UUID (case-insensitive) |
| `regex` | Valid regular expression |
| `json-pointer` | RFC 6901 JSON Pointer |
| `relative-json-pointer` | Relative JSON Pointer |
| `idn-hostname` | Internationalized domain name (IDNA UTS#46) |
| `idn-email` | Internationalized email address |
| `iri` | Internationalized Resource Identifier (RFC 3987) |
| `iri-reference` | IRI or relative IRI reference (RFC 3987) |

Unknown `format` values are silently ignored (per the JSON Schema specification, format validation is advisory).

Supported `contentEncoding` values: `base64`, `base64url`, `base32`, `base16`. Unknown encodings are silently ignored.

Supported `contentMediaType` values: `application/json`. Unknown media types are silently ignored.

To disable format and content validation:

```json
{ "formatValidation": false }
```

### `httpProxy`

- **Type:** `string` (optional)
- **Default:** `null` (no proxy)

HTTP proxy URL used for all schema fetching (individual schemas and the SchemaStore catalog). Format: `http://host:port` or `https://host:port`.

```json
{ "httpProxy": "http://proxy.corp:8080" }
```

When absent or `null`, requests are made directly. Invalid proxy URLs are silently ignored and requests fall back to direct connections.

### `colorDecorators`

- **Type:** `boolean` (optional)
- **Default:** `true`

Enable color picker integration for color values in YAML documents. When enabled, the server responds to `textDocument/documentColor` requests by detecting hex codes (`#rrggbb`, `#rgb`), CSS named colors (`red`, `blue`, etc.), and CSS color functions (`rgb()`, `rgba()`, `hsl()`, `hsla()`) in YAML values, and returns them to the editor for color picker decoration. The server also handles `textDocument/colorPresentation` requests to convert a picked color back to hex, RGB, or HSL notation.

To disable color decorators:

```json
{ "colorDecorators": false }
```

### `validate`

- **Type:** `boolean` (optional)
- **Default:** `true`

Enable or disable diagnostic validation. When `false`, the server publishes no diagnostics for any open document — syntax errors, duplicate keys, schema violations, and all other validators are suppressed. Existing diagnostics are cleared immediately when validation is disabled.

```json
{ "validate": false }
```

### `hover`

- **Type:** `boolean` (optional)
- **Default:** `true`

Enable or disable hover information. When `false`, the server returns no results for `textDocument/hover` requests.

```json
{ "hover": false }
```

### `completion`

- **Type:** `boolean` (optional)
- **Default:** `true`

Enable or disable completion suggestions. When `false`, the server returns no results for `textDocument/completion` requests.

```json
{ "completion": false }
```

### `maxItemsComputed`

- **Type:** `number` (optional)
- **Default:** `5000`

Maximum number of items returned by document symbol (`textDocument/documentSymbol`) and folding range (`textDocument/foldingRange`) requests. Results are truncated to this limit before being returned to the client. Setting this to `0` suppresses all results from these two requests.

This limit prevents performance degradation when editing very large YAML files that would otherwise produce thousands of symbols or folding regions.

```json
{ "maxItemsComputed": 1000 }
```

> **Indentation** (`tabWidth`, `useTabs`) is not configurable via workspace settings — it is taken directly from the LSP `textDocument/formatting` request, which carries the editor's indentation preferences. Configure indentation in your editor settings.

## Modelines

Modelines are special YAML comments in the **first 10 lines** of a file. They override workspace settings on a per-document basis.

### Schema modeline

```yaml
# yaml-language-server: $schema=<url>
```

Associates the document with a JSON Schema URL. This takes priority over any workspace `schemas` glob match.

**Disable schema validation** for a single file:

```yaml
# yaml-language-server: $schema=none
```

The `none` sentinel (case-insensitive) disables schema fetching and schema-driven validation for that document. Other validators (duplicate keys, anchors, flow style) still run.

### Custom tags modeline

```yaml
# yaml-language-server: $tags=!include,!ref,!custom
```

Declares additional custom tags for the document. These are merged with the workspace `customTags` setting — both sources contribute to the allowed tag set.

### YAML version modeline

```yaml
# yaml-language-server: $yamlVersion=1.1
```

Overrides the workspace `yamlVersion` setting for this document. Accepted values: `1.1` and `1.2`. Any other value is ignored and the workspace setting applies.

Useful in mixed repositories where different files target different YAML versions — for example, Ansible playbooks (YAML 1.1) alongside Kubernetes manifests (YAML 1.2):

```yaml
# yaml-language-server: $yamlVersion=1.1
# Ansible playbook — on/off/yes/no are boolean keywords here
- hosts: all
  become: yes
```

## Diagnostic Suppression

Diagnostics can be silenced on a per-line or per-file basis using suppression comments. This is useful for false positives or intentional style deviations without disabling a validator globally.

### Suppress the next line

```yaml
# rlsp-yaml-disable-next-line
key: value  # all diagnostics on this line are suppressed
```

```yaml
# rlsp-yaml-disable-next-line duplicateKey
name: first
name: second  # duplicateKey suppressed; other codes still reported
```

```yaml
# rlsp-yaml-disable-next-line duplicateKey, flowMap
```

The comment must appear on the line **immediately before** the line to suppress. Only the one following line is affected.

### Suppress the entire file

```yaml
# rlsp-yaml-disable-file flowMap
config: {a: 1, b: 2}  # no flowMap warning anywhere in this file
```

```yaml
# rlsp-yaml-disable-file
# all diagnostics suppressed for this file
```

The comment can appear anywhere in the file. The first `# rlsp-yaml-disable-file` comment wins; subsequent ones are ignored.

### Available diagnostic codes

| Code | Emitted by |
|------|-----------|
| `duplicateKey` | Duplicate mapping key in the same scope |
| `flowMap` | Flow mapping (`{a: 1}`) where block style is preferred |
| `flowSeq` | Flow sequence (`[a, b]`) where block style is preferred |
| `unusedAnchor` | Anchor defined but never aliased |
| `unresolvedAlias` | Alias references an undefined anchor |
| `unknownTag` | Tag not in the allowed `customTags` list |
| `mapKeyOrder` | Mapping keys not in alphabetical order (requires `keyOrdering: true`) |
| `yamlSyntax` | YAML parse error |
| `schemaRequired` | Required property missing (JSON Schema `required`) |
| `schemaType` | Value does not match declared JSON Schema type |
| `schemaEnum` | Value not in the declared `enum` list |
| `schemaAdditionalProperty` | Additional property not allowed by schema |
| `schemaFormat` | Value does not match declared `format` (requires `formatValidation: true`) |
| `schemaContentEncoding` | Value cannot be decoded with declared `contentEncoding` |
| `schemaContentMediaType` | Decoded content does not match declared `contentMediaType` |

Codes not listed here (e.g. codes produced by future validators) can also be suppressed — the suppression comment accepts any string code.

## Validators

Some validators are always active; others depend on settings.

| Validator | Controlled by | Default |
|-----------|---------------|---------|
| YAML syntax errors | `validate` | on |
| Duplicate key detection | `validate` | on |
| Unused anchor warnings | `validate` | on |
| Flow style warnings | `validate` | on |
| Key ordering | `keyOrdering` | off |
| Custom tag validation | `customTags` | off (empty = disabled) |
| JSON Schema validation | `schemas` / modeline / K8s auto-detect / SchemaStore | off (no schema = disabled) |
| Schema `format` keyword validation | `formatValidation` | on (when schema is active) |
| SchemaStore auto-association | `schemaStore` | on |

## Formatting

The server implements `textDocument/formatting` for full-document YAML formatting and `textDocument/rangeFormatting` for formatting a selected region.

**Behavior:**

- **Indentation** (tab size, tabs vs spaces) is controlled by the editor — the LSP formatting requests carry `tab_size` and `insert_spaces` from the editor's own settings.
- **Style options** (print width, quote style) are controlled via workspace settings (`formatPrintWidth`, `formatSingleQuote`).
- **Comments** are preserved during formatting. The formatter extracts comments from the original text and reattaches them to the formatted output.
- **Syntax errors** — if the document cannot be parsed, the original text is returned unchanged so no content is lost.

**Range formatting** uses the same settings and formatter as full-document formatting. The full document is formatted internally and the resulting lines that correspond to the requested range are returned as the edit. This ensures consistent line-breaking decisions — the printer needs surrounding context to make correct choices.

The formatter is built on `rlsp-fmt`, an internal Wadler-Lindig pretty-printing engine. It walks the parsed AST and emits IR nodes that the engine renders with line-width awareness.

## Schema Resolution Priority

When a YAML file is opened or changed, the server resolves a schema using the following chain (first match wins):

1. **Modeline**`# yaml-language-server: $schema=<url>` in the first 10 lines of the file. Highest priority; overrides everything else. Use `$schema=none` to disable schema processing for a specific file.
2. **Workspace glob** — the `schemas` setting maps schema URLs to glob patterns. The first pattern that matches the file's URI path wins.
3. **Kubernetes auto-detection** — if the document's root mapping contains both `apiVersion` and `kind`, the server fetches the corresponding schema from [yannh/kubernetes-json-schema]https://github.com/yannh/kubernetes-json-schema using the configured `kubernetesVersion`.
4. **SchemaStore** — if enabled (`schemaStore: true`, the default), the server fetches the [SchemaStore]https://www.schemastore.org/ catalog and matches the file's path against catalog `fileMatch` patterns. The catalog is fetched lazily on first need and cached for the session.

If none of the above produce a match, no schema is applied and only syntax/structural validators run.

## Schema Fetching

Schemas are fetched over HTTP/HTTPS and cached in memory for the session.

**Limits:**
- Maximum URL length: 2048 characters
- Maximum response size: 5 MiB
- Maximum JSON nesting depth: 50
- Maximum `$ref` resolution depth: 32
- Redirects: disabled
- Connection timeout: 5 seconds
- Total request timeout: 15 seconds

**SSRF protection** — the server blocks schema URLs that resolve to:
- Loopback addresses (`127.0.0.0/8`, `::1`, `localhost`)
- Private networks (`10.0.0.0/8`, `172.16.0.0/12`, `192.168.0.0/16`)
- Link-local addresses (`169.254.0.0/16`, `fe80::/10`)
- Unspecified addresses (`0.0.0.0`, `::`)