@marko/language-server 1.0.20 → 1.1.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.
package/dist/index.mjs CHANGED
@@ -3,7 +3,7 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
3
3
  }) : x)(function(x) {
4
4
  if (typeof require !== "undefined")
5
5
  return require.apply(this, arguments);
6
- throw new Error('Dynamic require of "' + x + '" is not supported');
6
+ throw Error('Dynamic require of "' + x + '" is not supported');
7
7
  });
8
8
 
9
9
  // src/index.ts
@@ -76,7 +76,9 @@ function processDoc(doc, process2) {
76
76
  // src/utils/text-documents.ts
77
77
  import fs from "fs";
78
78
  import { URI as URI2 } from "vscode-uri";
79
- import { FileChangeType } from "vscode-languageserver";
79
+ import {
80
+ FileChangeType
81
+ } from "vscode-languageserver";
80
82
  import { TextDocument } from "vscode-languageserver-textdocument";
81
83
  var docs = /* @__PURE__ */ new Map();
82
84
  var openDocs = /* @__PURE__ */ new Set();
@@ -132,67 +134,65 @@ function exists(uri) {
132
134
  function isOpen(doc) {
133
135
  return openDocs.has(doc);
134
136
  }
135
- function setup(connection4) {
136
- connection4.onDidOpenTextDocument((params) => {
137
- const ref = params.textDocument;
138
- const existingDoc = docs.get(ref.uri);
137
+ function doOpen(params) {
138
+ const ref = params.textDocument;
139
+ const existingDoc = docs.get(ref.uri);
140
+ projectVersion++;
141
+ if (existingDoc) {
142
+ if (existingDoc.version === ref.version) {
143
+ openDocs.add(existingDoc);
144
+ return;
145
+ }
146
+ openDocs.delete(existingDoc);
147
+ docs.delete(ref.uri);
148
+ }
149
+ const newDoc = TextDocument.create(
150
+ ref.uri,
151
+ ref.languageId,
152
+ ref.version,
153
+ ref.text
154
+ );
155
+ openDocs.add(newDoc);
156
+ fileExists.set(ref.uri, true);
157
+ docs.set(ref.uri, newDoc);
158
+ }
159
+ function doChange(params) {
160
+ const ref = params.textDocument;
161
+ const changes = params.contentChanges;
162
+ const doc = docs.get(ref.uri);
163
+ if (changes.length > 0 && ref.version != null && doc) {
164
+ TextDocument.update(doc, changes, ref.version);
165
+ emitFileChange(doc);
166
+ }
167
+ }
168
+ function doClose(params) {
169
+ const ref = params.textDocument;
170
+ const doc = docs.get(ref.uri);
171
+ if (doc) {
139
172
  projectVersion++;
140
- if (existingDoc) {
141
- if (existingDoc.version === ref.version) {
142
- openDocs.add(existingDoc);
143
- return;
144
- }
145
- openDocs.delete(existingDoc);
173
+ openDocs.delete(doc);
174
+ if (URI2.parse(ref.uri).scheme !== "file") {
146
175
  docs.delete(ref.uri);
147
176
  }
148
- const newDoc = TextDocument.create(
149
- ref.uri,
150
- ref.languageId,
151
- ref.version,
152
- ref.text
153
- );
154
- openDocs.add(newDoc);
155
- fileExists.set(ref.uri, true);
156
- docs.set(ref.uri, newDoc);
157
- });
158
- connection4.onDidChangeTextDocument((params) => {
159
- const ref = params.textDocument;
160
- const changes = params.contentChanges;
161
- const doc = docs.get(ref.uri);
162
- if (changes.length > 0 && ref.version != null && doc) {
163
- TextDocument.update(doc, changes, ref.version);
164
- emitFileChange(doc);
165
- }
166
- });
167
- connection4.onDidCloseTextDocument((params) => {
168
- const ref = params.textDocument;
169
- const doc = docs.get(ref.uri);
170
- if (doc) {
171
- projectVersion++;
172
- openDocs.delete(doc);
173
- if (URI2.parse(ref.uri).scheme !== "file") {
174
- docs.delete(ref.uri);
175
- }
176
- }
177
- });
178
- connection4.onDidChangeWatchedFiles(async (params) => {
179
- for (const change of params.changes) {
180
- switch (change.type) {
181
- case FileChangeType.Created:
182
- fileExists.set(change.uri, true);
183
- break;
184
- case FileChangeType.Deleted:
185
- case FileChangeType.Changed: {
186
- fileExists.set(change.uri, change.type === FileChangeType.Changed);
187
- const doc = docs.get(change.uri);
188
- if (doc && !openDocs.has(doc)) {
189
- docs.delete(change.uri);
190
- }
177
+ }
178
+ }
179
+ function doChangeWatchedFiles(params) {
180
+ for (const change of params.changes) {
181
+ switch (change.type) {
182
+ case FileChangeType.Created:
183
+ fileExists.set(change.uri, true);
184
+ break;
185
+ case FileChangeType.Deleted:
186
+ case FileChangeType.Changed: {
187
+ fileExists.set(change.uri, change.type === FileChangeType.Changed);
188
+ const doc = docs.get(change.uri);
189
+ if (doc && !openDocs.has(doc)) {
190
+ docs.delete(change.uri);
191
191
  }
192
192
  }
193
193
  }
194
- emitFileChange(void 0);
195
- });
194
+ }
195
+ emitFileChange(void 0);
196
196
  }
197
197
  function getLanguageId(uri) {
198
198
  const ext = uri.slice(uri.lastIndexOf(".") + 1);
@@ -217,6 +217,7 @@ function emitFileChange(doc) {
217
217
  }
218
218
 
219
219
  // src/utils/workspace.ts
220
+ var isInitialized = false;
220
221
  var connection;
221
222
  var configChangeHandlers = /* @__PURE__ */ new Set();
222
223
  var settingsCache = /* @__PURE__ */ new Map();
@@ -234,11 +235,15 @@ async function getConfig(section) {
234
235
  function onConfigChange(handler) {
235
236
  configChangeHandlers.add(handler);
236
237
  }
237
- function setup2(_) {
238
+ function setup(_) {
238
239
  connection = _;
239
240
  connection.onDidChangeConfiguration(() => {
240
- settingsCache.clear();
241
- emitConfigChange();
241
+ if (isInitialized) {
242
+ settingsCache.clear();
243
+ emitConfigChange();
244
+ } else {
245
+ isInitialized = true;
246
+ }
242
247
  });
243
248
  }
244
249
  function emitConfigChange() {
@@ -251,7 +256,7 @@ function emitConfigChange() {
251
256
  import { inspect } from "util";
252
257
  var connection2;
253
258
  var previousMessagesByType = /* @__PURE__ */ new Map();
254
- function setup3(_) {
259
+ function setup2(_) {
255
260
  connection2 = _;
256
261
  }
257
262
  function displayError(data) {
@@ -276,6 +281,750 @@ function display(type, data) {
276
281
  // src/service/index.ts
277
282
  import { MarkupContent, MarkupKind as MarkupKind3 } from "vscode-languageserver";
278
283
 
284
+ // src/service/html/index.ts
285
+ import axe from "axe-core";
286
+ import { extractHTML } from "@marko/language-tools";
287
+ import { JSDOM } from "jsdom";
288
+
289
+ // src/service/html/axe-rules/axe-rules.ts
290
+ var keyboard = {
291
+ /**
292
+ * - Ensures every accesskey attribute value is unique
293
+ * - accesskey attribute value should be unique ([url](https://dequeuniversity.com/rules/axe/4.4/accesskeys?application=axeAPI))
294
+ */
295
+ accesskeys: "accesskeys",
296
+ /**
297
+ * - Ensures each page has at least one mechanism for a user to bypass navigation and jump straight to the content
298
+ * - Page must have means to bypass repeated blocks ([url](https://dequeuniversity.com/rules/axe/4.4/bypass?application=axeAPI))
299
+ */
300
+ bypass: "bypass",
301
+ /**
302
+ * - Ensures elements in the focus order have a role appropriate for interactive content
303
+ * - Elements in the focus order should have an appropriate role ([url](https://dequeuniversity.com/rules/axe/4.4/focus-order-semantics?application=axeAPI))
304
+ */
305
+ focusOrderSemantics: "focus-order-semantics",
306
+ /**
307
+ * - Ensures `<frame>` and `<iframe>` elements with focusable content do not have tabindex=-1
308
+ * - Frames with focusable content must not have tabindex=-1 ([url](https://dequeuniversity.com/rules/axe/4.4/frame-focusable-content?application=axeAPI))
309
+ */
310
+ frameFocusableContent: "frame-focusable-content",
311
+ /**
312
+ * - Ensures interactive controls are not nested as they are not always announced by screen readers or can cause focus problems for assistive technologies
313
+ * - Interactive controls must not be nested ([url](https://dequeuniversity.com/rules/axe/4.4/nested-interactive?application=axeAPI))
314
+ */
315
+ nestedInteractive: "nested-interactive",
316
+ /**
317
+ * - Ensures all page content is contained by landmarks
318
+ * - All page content should be contained by landmarks ([url](https://dequeuniversity.com/rules/axe/4.4/region?application=axeAPI))
319
+ */
320
+ region: "region",
321
+ /**
322
+ * - Ensure elements that have scrollable content are accessible by keyboard
323
+ * - Scrollable region must have keyboard access ([url](https://dequeuniversity.com/rules/axe/4.4/scrollable-region-focusable?application=axeAPI))
324
+ */
325
+ scrollableRegionFocusable: "scrollable-region-focusable",
326
+ /**
327
+ * - Ensure all skip links have a focusable target
328
+ * - The skip-link target should exist and be focusable ([url](https://dequeuniversity.com/rules/axe/4.4/skip-link?application=axeAPI))
329
+ */
330
+ skipLink: "skip-link",
331
+ /**
332
+ * - Ensures tabindex attribute values are not greater than 0
333
+ * - Elements should not have tabindex greater than zero ([url](https://dequeuniversity.com/rules/axe/4.4/tabindex?application=axeAPI))
334
+ */
335
+ tabindex: "tabindex"
336
+ };
337
+ var textAlternatives = {
338
+ /**
339
+ * - Ensures `<area>` elements of image maps have alternate text
340
+ * - Active `<area>` elements must have alternate text ([url](https://dequeuniversity.com/rules/axe/4.4/area-alt?application=axeAPI))
341
+ */
342
+ areaAlt: "area-alt",
343
+ /**
344
+ * - Ensures each HTML document contains a non-empty `<title>` element
345
+ * - Documents must have `<title>` element to aid in navigation ([url](https://dequeuniversity.com/rules/axe/4.4/document-title?application=axeAPI))
346
+ */
347
+ documentTitle: "document-title",
348
+ /**
349
+ * - Ensures `<iframe>` and `<frame>` elements contain a unique title attribute
350
+ * - Frames should have a unique title attribute ([url](https://dequeuniversity.com/rules/axe/4.4/frame-title-unique?application=axeAPI))
351
+ */
352
+ frameTitleUnique: "frame-title-unique",
353
+ /**
354
+ * - Ensures `<iframe>` and `<frame>` elements have an accessible name
355
+ * - Frames must have an accessible name ([url](https://dequeuniversity.com/rules/axe/4.4/frame-title?application=axeAPI))
356
+ */
357
+ frameTitle: "frame-title",
358
+ /**
359
+ * - Ensures `<img>` elements have alternate text or a role of none or presentation
360
+ * - Images must have alternate text ([url](https://dequeuniversity.com/rules/axe/4.4/image-alt?application=axeAPI))
361
+ */
362
+ imageAlt: "image-alt",
363
+ /**
364
+ * - Ensure image alternative is not repeated as text
365
+ * - Alternative text of images should not be repeated as text ([url](https://dequeuniversity.com/rules/axe/4.4/image-redundant-alt?application=axeAPI))
366
+ */
367
+ imageRedundantAlt: "image-redundant-alt",
368
+ /**
369
+ * - Ensures `<input type="image">` elements have alternate text
370
+ * - Image buttons must have alternate text ([url](https://dequeuniversity.com/rules/axe/4.4/input-image-alt?application=axeAPI))
371
+ */
372
+ inputImageAlt: "input-image-alt",
373
+ /**
374
+ * - Ensures `<object>` elements have alternate text
375
+ * - `<object>` elements must have alternate text ([url](https://dequeuniversity.com/rules/axe/4.4/object-alt?application=axeAPI))
376
+ */
377
+ objectAlt: "object-alt",
378
+ /**
379
+ * - Ensures [role='img'] elements have alternate text
380
+ * - [role='img'] elements must have an alternative text ([url](https://dequeuniversity.com/rules/axe/4.4/role-img-alt?application=axeAPI))
381
+ */
382
+ roleImgAlt: "role-img-alt",
383
+ /**
384
+ * - Ensures that server-side image maps are not used
385
+ * - Server-side image maps must not be used ([url](https://dequeuniversity.com/rules/axe/4.4/server-side-image-map?application=axeAPI))
386
+ */
387
+ serverSideImageMap: "server-side-image-map",
388
+ /**
389
+ * - Ensures `<svg>` elements with an img, graphics-document or graphics-symbol role have an accessible text
390
+ * - `<svg>` elements with an img role must have an alternative text ([url](https://dequeuniversity.com/rules/axe/4.4/svg-img-alt?application=axeAPI))
391
+ */
392
+ svgImgAlt: "svg-img-alt",
393
+ /**
394
+ * - Ensures `<video>` elements have captions
395
+ * - `<video>` elements must have captions ([url](https://dequeuniversity.com/rules/axe/4.4/video-caption?application=axeAPI))
396
+ */
397
+ videoCaption: "video-caption"
398
+ };
399
+ var aria = {
400
+ /**
401
+ * - Ensures ARIA attributes are allowed for an element's role
402
+ * - Elements must only use allowed ARIA attributes ([url](https://dequeuniversity.com/rules/axe/4.4/aria-allowed-attr?application=axeAPI))
403
+ */
404
+ ariaAllowedAttr: "aria-allowed-attr",
405
+ /**
406
+ * - Ensures role attribute has an appropriate value for the element
407
+ * - ARIA role should be appropriate for the element ([url](https://dequeuniversity.com/rules/axe/4.4/aria-allowed-role?application=axeAPI))
408
+ */
409
+ ariaAllowedRole: "aria-allowed-role",
410
+ /**
411
+ * - Ensures every ARIA button, link and menuitem has an accessible name
412
+ * - ARIA commands must have an accessible name ([url](https://dequeuniversity.com/rules/axe/4.4/aria-command-name?application=axeAPI))
413
+ */
414
+ ariaCommandName: "aria-command-name",
415
+ /**
416
+ * - Ensures every ARIA dialog and alertdialog node has an accessible name
417
+ * - ARIA dialog and alertdialog nodes should have an accessible name ([url](https://dequeuniversity.com/rules/axe/4.4/aria-dialog-name?application=axeAPI))
418
+ */
419
+ ariaDialogName: "aria-dialog-name",
420
+ /**
421
+ * - Ensures aria-hidden='true' is not present on the document body.
422
+ * - aria-hidden='true' must not be present on the document body ([url](https://dequeuniversity.com/rules/axe/4.4/aria-hidden-body?application=axeAPI))
423
+ */
424
+ ariaHiddenBody: "aria-hidden-body",
425
+ /**
426
+ * - Ensures every ARIA input field has an accessible name
427
+ * - ARIA input fields must have an accessible name ([url](https://dequeuniversity.com/rules/axe/4.4/aria-input-field-name?application=axeAPI))
428
+ */
429
+ ariaInputFieldName: "aria-input-field-name",
430
+ /**
431
+ * - Ensures every ARIA meter node has an accessible name
432
+ * - ARIA meter nodes must have an accessible name ([url](https://dequeuniversity.com/rules/axe/4.4/aria-meter-name?application=axeAPI))
433
+ */
434
+ ariaMeterName: "aria-meter-name",
435
+ /**
436
+ * - Ensures every ARIA progressbar node has an accessible name
437
+ * - ARIA progressbar nodes must have an accessible name ([url](https://dequeuniversity.com/rules/axe/4.4/aria-progressbar-name?application=axeAPI))
438
+ */
439
+ ariaProgressbarName: "aria-progressbar-name",
440
+ /**
441
+ * - Ensures elements with ARIA roles have all required ARIA attributes
442
+ * - Required ARIA attributes must be provided ([url](https://dequeuniversity.com/rules/axe/4.4/aria-required-attr?application=axeAPI))
443
+ */
444
+ ariaRequiredAttr: "aria-required-attr",
445
+ /**
446
+ * - Ensures elements with an ARIA role that require child roles contain them
447
+ * - Certain ARIA roles must contain particular children ([url](https://dequeuniversity.com/rules/axe/4.4/aria-required-children?application=axeAPI))
448
+ */
449
+ ariaRequiredChildren: "aria-required-children",
450
+ /**
451
+ * - Ensures elements with an ARIA role that require parent roles are contained by them
452
+ * - Certain ARIA roles must be contained by particular parents ([url](https://dequeuniversity.com/rules/axe/4.4/aria-required-parent?application=axeAPI))
453
+ */
454
+ ariaRequiredParent: "aria-required-parent",
455
+ /**
456
+ * - Ensure aria-roledescription is only used on elements with an implicit or explicit role
457
+ * - aria-roledescription must be on elements with a semantic role ([url](https://dequeuniversity.com/rules/axe/4.4/aria-roledescription?application=axeAPI))
458
+ */
459
+ ariaRoledescription: "aria-roledescription",
460
+ /**
461
+ * - Ensures all elements with a role attribute use a valid value
462
+ * - ARIA roles used must conform to valid values ([url](https://dequeuniversity.com/rules/axe/4.4/aria-roles?application=axeAPI))
463
+ */
464
+ ariaRoles: "aria-roles",
465
+ /**
466
+ * - Ensures "role=text" is used on elements with no focusable descendants
467
+ * - "role=text" should have no focusable descendants ([url](https://dequeuniversity.com/rules/axe/4.4/aria-text?application=axeAPI))
468
+ */
469
+ ariaText: "aria-text",
470
+ /**
471
+ * - Ensures every ARIA toggle field has an accessible name
472
+ * - ARIA toggle fields must have an accessible name ([url](https://dequeuniversity.com/rules/axe/4.4/aria-toggle-field-name?application=axeAPI))
473
+ */
474
+ ariaToggleFieldName: "aria-toggle-field-name",
475
+ /**
476
+ * - Ensures every ARIA tooltip node has an accessible name
477
+ * - ARIA tooltip nodes must have an accessible name ([url](https://dequeuniversity.com/rules/axe/4.4/aria-tooltip-name?application=axeAPI))
478
+ */
479
+ ariaTooltipName: "aria-tooltip-name",
480
+ /**
481
+ * - Ensures every ARIA treeitem node has an accessible name
482
+ * - ARIA treeitem nodes should have an accessible name ([url](https://dequeuniversity.com/rules/axe/4.4/aria-treeitem-name?application=axeAPI))
483
+ */
484
+ ariaTreeitemName: "aria-treeitem-name",
485
+ /**
486
+ * - Ensures all ARIA attributes have valid values
487
+ * - ARIA attributes must conform to valid values ([url](https://dequeuniversity.com/rules/axe/4.4/aria-valid-attr-value?application=axeAPI))
488
+ */
489
+ ariaValidAttrValue: "aria-valid-attr-value",
490
+ /**
491
+ * - Ensures attributes that begin with aria- are valid ARIA attributes
492
+ * - ARIA attributes must conform to valid names ([url](https://dequeuniversity.com/rules/axe/4.4/aria-valid-attr?application=axeAPI))
493
+ */
494
+ ariaValidAttr: "aria-valid-attr",
495
+ /**
496
+ * - Ensures table headers have discernible text
497
+ * - Table header text must not be empty ([url](https://dequeuniversity.com/rules/axe/4.4/empty-table-header?application=axeAPI))
498
+ */
499
+ emptyTableHeader: "empty-table-header",
500
+ /**
501
+ * - Flags elements whose role is none or presentation and which cause the role conflict resolution to trigger.
502
+ * - Elements of role none or presentation should be flagged ([url](https://dequeuniversity.com/rules/axe/4.4/presentation-role-conflict?application=axeAPI))
503
+ */
504
+ presentationRoleConflict: "presentation-role-conflict"
505
+ };
506
+ var nameRoleValue = {
507
+ /**
508
+ * - Ensures aria-hidden elements are not focusable nor contain focusable elements
509
+ * - ARIA hidden element must not be focusable or contain focusable elements ([url](https://dequeuniversity.com/rules/axe/4.4/aria-hidden-focus?application=axeAPI))
510
+ */
511
+ ariaHiddenFocus: "aria-hidden-focus",
512
+ /**
513
+ * - Ensures buttons have discernible text
514
+ * - Buttons must have discernible text ([url](https://dequeuniversity.com/rules/axe/4.4/button-name?application=axeAPI))
515
+ */
516
+ buttonName: "button-name",
517
+ /**
518
+ * - Ensures headings have discernible text
519
+ * - Headings should not be empty ([url](https://dequeuniversity.com/rules/axe/4.4/empty-heading?application=axeAPI))
520
+ */
521
+ emptyHeading: "empty-heading",
522
+ /**
523
+ * - Ensures input buttons have discernible text
524
+ * - Input buttons must have discernible text ([url](https://dequeuniversity.com/rules/axe/4.4/input-button-name?application=axeAPI))
525
+ */
526
+ inputButtonName: "input-button-name",
527
+ /**
528
+ * - Ensures links have discernible text
529
+ * - Links must have discernible text ([url](https://dequeuniversity.com/rules/axe/4.4/link-name?application=axeAPI))
530
+ */
531
+ linkName: "link-name"
532
+ };
533
+ var timeAndMedia = {
534
+ /**
535
+ * - Ensures `<audio>` elements have captions
536
+ * - `<audio>` elements must have a captions track ([url](https://dequeuniversity.com/rules/axe/4.4/audio-caption?application=axeAPI))
537
+ */
538
+ audioCaption: "audio-caption",
539
+ /**
540
+ * - Ensures `<blink>` elements are not used
541
+ * - `<blink>` elements are deprecated and must not be used ([url](https://dequeuniversity.com/rules/axe/4.4/blink?application=axeAPI))
542
+ */
543
+ blink: "blink",
544
+ /**
545
+ * - Ensures `<meta http-equiv="refresh">` is not used
546
+ * - Timed refresh must not exist ([url](https://dequeuniversity.com/rules/axe/4.4/meta-refresh?application=axeAPI))
547
+ */
548
+ metaRefresh: "meta-refresh",
549
+ /**
550
+ * - Ensures `<video>` or `<audio>` elements do not autoplay audio for more than 3 seconds without a control mechanism to stop or mute the audio
551
+ * - `<video>` or `<audio>` elements must not play automatically ([url](https://dequeuniversity.com/rules/axe/4.4/no-autoplay-audio?application=axeAPI))
552
+ */
553
+ noAutoplayAudio: "no-autoplay-audio"
554
+ };
555
+ var forms = {
556
+ /**
557
+ * - Ensure the autocomplete attribute is correct and suitable for the form field
558
+ * - autocomplete attribute must be used correctly ([url](https://dequeuniversity.com/rules/axe/4.4/autocomplete-valid?application=axeAPI))
559
+ */
560
+ autocompleteValid: "autocomplete-valid",
561
+ /**
562
+ * - Ensures form field does not have multiple label elements
563
+ * - Form field must not have multiple label elements ([url](https://dequeuniversity.com/rules/axe/4.4/form-field-multiple-labels?application=axeAPI))
564
+ */
565
+ formFieldMultipleLabels: "form-field-multiple-labels",
566
+ /**
567
+ * - Ensures that every form element has a visible label and is not solely labeled using hidden labels, or the title or aria-describedby attributes
568
+ * - Form elements should have a visible label ([url](https://dequeuniversity.com/rules/axe/4.4/label-title-only?application=axeAPI))
569
+ */
570
+ labelTitleOnly: "label-title-only",
571
+ /**
572
+ * - Ensures every form element has a label
573
+ * - Form elements must have labels ([url](https://dequeuniversity.com/rules/axe/4.4/label?application=axeAPI))
574
+ */
575
+ label: "label",
576
+ /**
577
+ * - Ensures select element has an accessible name
578
+ * - Select element must have an accessible name ([url](https://dequeuniversity.com/rules/axe/4.4/select-name?application=axeAPI))
579
+ */
580
+ selectName: "select-name"
581
+ };
582
+ var structure = {
583
+ /**
584
+ * - Ensure that text spacing set through style attributes can be adjusted with custom stylesheets
585
+ * - Inline text spacing must be adjustable with custom stylesheets ([url](https://dequeuniversity.com/rules/axe/4.4/avoid-inline-spacing?application=axeAPI))
586
+ */
587
+ avoidInlineSpacing: "avoid-inline-spacing",
588
+ /**
589
+ * - Ensures content is not locked to any specific display orientation, and the content is operable in all display orientations
590
+ * - CSS Media queries must not lock display orientation ([url](https://dequeuniversity.com/rules/axe/4.4/css-orientation-lock?application=axeAPI))
591
+ */
592
+ cssOrientationLock: "css-orientation-lock",
593
+ /**
594
+ * - Ensures `<dl>` elements are structured correctly
595
+ * - `<dl>` elements must only directly contain properly-ordered `<dt>` and `<dd>` groups, `<script>`, `<template>` or `<div>` elements ([url](https://dequeuniversity.com/rules/axe/4.4/definition-list?application=axeAPI))
596
+ */
597
+ definitionList: "definition-list",
598
+ /**
599
+ * - Ensures `<dt>` and `<dd>` elements are contained by a `<dl>`
600
+ * - `<dt>` and `<dd>` elements must be contained by a `<dl>` ([url](https://dequeuniversity.com/rules/axe/4.4/dlitem?application=axeAPI))
601
+ */
602
+ dlitem: "dlitem",
603
+ /**
604
+ * - Ensures `<iframe>` and `<frame>` elements contain the axe-core script
605
+ * - Frames should be tested with axe-core ([url](https://dequeuniversity.com/rules/axe/4.4/frame-tested?application=axeAPI))
606
+ */
607
+ frameTested: "frame-tested",
608
+ /**
609
+ * - Informs users about hidden content.
610
+ * - Hidden content on the page should be analyzed ([url](https://dequeuniversity.com/rules/axe/4.4/hidden-content?application=axeAPI))
611
+ */
612
+ hiddenContent: "hidden-content",
613
+ /**
614
+ * - Ensures that lists are structured correctly
615
+ * - `<ul>` and `<ol>` must only directly contain `<li>`, `<script>` or `<template>` elements ([url](https://dequeuniversity.com/rules/axe/4.4/list?application=axeAPI))
616
+ */
617
+ list: "list",
618
+ /**
619
+ * - Ensures `<li>` elements are used semantically
620
+ * - `<li>` elements must be contained in a `<ul>` or `<ol>` ([url](https://dequeuniversity.com/rules/axe/4.4/listitem?application=axeAPI))
621
+ */
622
+ listitem: "listitem"
623
+ };
624
+ var parsing = {
625
+ /**
626
+ * - Ensures every id attribute value of active elements is unique
627
+ * - IDs of active elements must be unique ([url](https://dequeuniversity.com/rules/axe/4.4/duplicate-id-active?application=axeAPI))
628
+ */
629
+ duplicateIdActive: "duplicate-id-active",
630
+ /**
631
+ * - Ensures every id attribute value used in ARIA and in labels is unique
632
+ * - IDs used in ARIA and labels must be unique ([url](https://dequeuniversity.com/rules/axe/4.4/duplicate-id-aria?application=axeAPI))
633
+ */
634
+ duplicateIdAria: "duplicate-id-aria",
635
+ /**
636
+ * - Ensures every id attribute value is unique
637
+ * - id attribute value must be unique ([url](https://dequeuniversity.com/rules/axe/4.4/duplicate-id?application=axeAPI))
638
+ */
639
+ duplicateId: "duplicate-id",
640
+ /**
641
+ * - Ensures `<marquee>` elements are not used
642
+ * - `<marquee>` elements are deprecated and must not be used ([url](https://dequeuniversity.com/rules/axe/4.4/marquee?application=axeAPI))
643
+ */
644
+ marquee: "marquee"
645
+ };
646
+ var semantics = {
647
+ /**
648
+ * - Ensures the order of headings is semantically correct
649
+ * - Heading levels should only increase by one ([url](https://dequeuniversity.com/rules/axe/4.4/heading-order?application=axeAPI))
650
+ */
651
+ headingOrder: "heading-order",
652
+ /**
653
+ * - Ensure that links with the same accessible name serve a similar purpose
654
+ * - Links with the same name must have a similar purpose ([url](https://dequeuniversity.com/rules/axe/4.4/identical-links-same-purpose?application=axeAPI))
655
+ */
656
+ identicalLinksSamePurpose: "identical-links-same-purpose",
657
+ /**
658
+ * - Ensures that elements labelled through their content must have their visible text as part of their accessible name
659
+ * - Elements must have their visible text as part of their accessible name ([url](https://dequeuniversity.com/rules/axe/4.4/label-content-name-mismatch?application=axeAPI))
660
+ */
661
+ labelContentNameMismatch: "label-content-name-mismatch",
662
+ /**
663
+ * - Ensures the banner landmark is at top level
664
+ * - Banner landmark should not be contained in another landmark ([url](https://dequeuniversity.com/rules/axe/4.4/landmark-banner-is-top-level?application=axeAPI))
665
+ */
666
+ landmarkBannerIsTopLevel: "landmark-banner-is-top-level",
667
+ /**
668
+ * - Ensures the complementary landmark or aside is at top level
669
+ * - Aside should not be contained in another landmark ([url](https://dequeuniversity.com/rules/axe/4.4/landmark-complementary-is-top-level?application=axeAPI))
670
+ */
671
+ landmarkComplementaryIsTopLevel: "landmark-complementary-is-top-level",
672
+ /**
673
+ * - Ensures the contentinfo landmark is at top level
674
+ * - Contentinfo landmark should not be contained in another landmark ([url](https://dequeuniversity.com/rules/axe/4.4/landmark-contentinfo-is-top-level?application=axeAPI))
675
+ */
676
+ landmarkContentinfoIsTopLevel: "landmark-contentinfo-is-top-level",
677
+ /**
678
+ * - Ensures the main landmark is at top level
679
+ * - Main landmark should not be contained in another landmark ([url](https://dequeuniversity.com/rules/axe/4.4/landmark-main-is-top-level?application=axeAPI))
680
+ */
681
+ landmarkMainIsTopLevel: "landmark-main-is-top-level",
682
+ /**
683
+ * - Ensures the document has at most one banner landmark
684
+ * - Document should not have more than one banner landmark ([url](https://dequeuniversity.com/rules/axe/4.4/landmark-no-duplicate-banner?application=axeAPI))
685
+ */
686
+ landmarkNoDuplicateBanner: "landmark-no-duplicate-banner",
687
+ /**
688
+ * - Ensures the document has at most one contentinfo landmark
689
+ * - Document should not have more than one contentinfo landmark ([url](https://dequeuniversity.com/rules/axe/4.4/landmark-no-duplicate-contentinfo?application=axeAPI))
690
+ */
691
+ landmarkNoDuplicateContentinfo: "landmark-no-duplicate-contentinfo",
692
+ /**
693
+ * - Ensures the document has at most one main landmark
694
+ * - Document should not have more than one main landmark ([url](https://dequeuniversity.com/rules/axe/4.4/landmark-no-duplicate-main?application=axeAPI))
695
+ */
696
+ landmarkNoDuplicateMain: "landmark-no-duplicate-main",
697
+ /**
698
+ * - Ensures the document has a main landmark
699
+ * - Document should have one main landmark ([url](https://dequeuniversity.com/rules/axe/4.4/landmark-one-main?application=axeAPI))
700
+ */
701
+ landmarkOneMain: "landmark-one-main",
702
+ /**
703
+ * - Landmarks should have a unique role or role/label/title (i.e. accessible name) combination
704
+ * - Ensures landmarks are unique ([url](https://dequeuniversity.com/rules/axe/4.4/landmark-unique?application=axeAPI))
705
+ */
706
+ landmarkUnique: "landmark-unique",
707
+ /**
708
+ * - Ensure bold, italic text and font-size is not used to style `<p>` elements as a heading
709
+ * - Styled `<p>` elements must not be used as headings ([url](https://dequeuniversity.com/rules/axe/4.4/p-as-heading?application=axeAPI))
710
+ */
711
+ pAsHeading: "p-as-heading",
712
+ /**
713
+ * - Ensure that the page, or at least one of its frames contains a level-one heading
714
+ * - Page should contain a level-one heading ([url](https://dequeuniversity.com/rules/axe/4.4/page-has-heading-one?application=axeAPI))
715
+ */
716
+ pageHasHeadingOne: "page-has-heading-one"
717
+ };
718
+ var language = {
719
+ /**
720
+ * - Ensures every HTML document has a lang attribute
721
+ * - `<html>` element must have a lang attribute ([url](https://dequeuniversity.com/rules/axe/4.4/html-has-lang?application=axeAPI))
722
+ */
723
+ htmlHasLang: "html-has-lang",
724
+ /**
725
+ * - Ensures the lang attribute of the `<html>` element has a valid value
726
+ * - `<html>` element must have a valid value for the lang attribute ([url](https://dequeuniversity.com/rules/axe/4.4/html-lang-valid?application=axeAPI))
727
+ */
728
+ htmlLangValid: "html-lang-valid",
729
+ /**
730
+ * - Ensure that HTML elements with both valid lang and xml:lang attributes agree on the base language of the page
731
+ * - HTML elements with lang and xml:lang must have the same base language ([url](https://dequeuniversity.com/rules/axe/4.4/html-xml-lang-mismatch?application=axeAPI))
732
+ */
733
+ htmlXmlLangMismatch: "html-xml-lang-mismatch",
734
+ /**
735
+ * - Ensures lang attributes have valid values
736
+ * - lang attribute must have a valid value ([url](https://dequeuniversity.com/rules/axe/4.4/valid-lang?application=axeAPI))
737
+ */
738
+ validLang: "valid-lang"
739
+ };
740
+ var sensoryAndVisualCues = {
741
+ /**
742
+ * - Ensures `<meta name="viewport">` can scale a significant amount
743
+ * - Users should be able to zoom and scale the text up to 500% ([url](https://dequeuniversity.com/rules/axe/4.4/meta-viewport-large?application=axeAPI))
744
+ */
745
+ metaViewportLarge: "meta-viewport-large",
746
+ /**
747
+ * - Ensures `<meta name="viewport">` does not disable text scaling and zooming
748
+ * - Zooming and scaling should not be disabled ([url](https://dequeuniversity.com/rules/axe/4.4/meta-viewport?application=axeAPI))
749
+ */
750
+ metaViewport: "meta-viewport"
751
+ };
752
+ var tables = {
753
+ /**
754
+ * - Ensures the scope attribute is used correctly on tables
755
+ * - scope attribute should be used correctly ([url](https://dequeuniversity.com/rules/axe/4.4/scope-attr-valid?application=axeAPI))
756
+ */
757
+ scopeAttrValid: "scope-attr-valid",
758
+ /**
759
+ * - Ensure the `<caption>` element does not contain the same text as the summary attribute
760
+ * - tables should not have the same summary and caption ([url](https://dequeuniversity.com/rules/axe/4.4/table-duplicate-name?application=axeAPI))
761
+ */
762
+ tableDuplicateName: "table-duplicate-name",
763
+ /**
764
+ * - Ensure that tables with a caption use the `<caption>` element.
765
+ * - Data or header cells must not be used to give caption to a data table. ([url](https://dequeuniversity.com/rules/axe/4.4/table-fake-caption?application=axeAPI))
766
+ */
767
+ tableFakeCaption: "table-fake-caption",
768
+ /**
769
+ * - Ensure that each non-empty data cell in a `<table>` larger than 3 by 3 has one or more table headers
770
+ * - Non-empty `<td>` elements in larger `<table>` must have an associated table header ([url](https://dequeuniversity.com/rules/axe/4.4/td-has-header?application=axeAPI))
771
+ */
772
+ tdHasHeader: "td-has-header",
773
+ /**
774
+ * - Ensure that each cell in a table that uses the headers attribute refers only to other cells in that table
775
+ * - Table cells that use the headers attribute must only refer to cells in the same table ([url](https://dequeuniversity.com/rules/axe/4.4/td-headers-attr?application=axeAPI))
776
+ */
777
+ tdHeadersAttr: "td-headers-attr",
778
+ /**
779
+ * - Ensure that `<th>` elements and elements with role=columnheader/rowheader have data cells they describe
780
+ * - Table headers in a data table must refer to data cells ([url](https://dequeuniversity.com/rules/axe/4.4/th-has-data-cells?application=axeAPI))
781
+ */
782
+ thHasDataCells: "th-has-data-cells"
783
+ };
784
+
785
+ // src/service/html/axe-rules/separated-rules.ts
786
+ var rules = {
787
+ /**
788
+ * These rules can be evaluated against any component.
789
+ */
790
+ alwaysAllowed: [
791
+ aria.ariaAllowedAttr,
792
+ aria.ariaAllowedRole,
793
+ aria.ariaHiddenBody,
794
+ aria.ariaRoledescription,
795
+ aria.ariaRoles,
796
+ aria.presentationRoleConflict,
797
+ forms.autocompleteValid,
798
+ forms.formFieldMultipleLabels,
799
+ // Could not find error state
800
+ keyboard.accesskeys,
801
+ keyboard.focusOrderSemantics,
802
+ keyboard.tabindex,
803
+ language.htmlLangValid,
804
+ language.htmlXmlLangMismatch,
805
+ language.validLang,
806
+ nameRoleValue.ariaHiddenFocus,
807
+ // Could not find error state
808
+ nameRoleValue.emptyHeading,
809
+ parsing.duplicateIdActive,
810
+ parsing.duplicateIdAria,
811
+ parsing.marquee,
812
+ semantics.identicalLinksSamePurpose,
813
+ // Could not find error state
814
+ semantics.landmarkNoDuplicateBanner,
815
+ semantics.landmarkNoDuplicateContentinfo,
816
+ semantics.landmarkNoDuplicateMain,
817
+ semantics.landmarkUnique,
818
+ sensoryAndVisualCues.metaViewportLarge,
819
+ // Could not find error state
820
+ sensoryAndVisualCues.metaViewport,
821
+ // Could not find error state
822
+ tables.scopeAttrValid,
823
+ // Could not find error state
824
+ textAlternatives.serverSideImageMap,
825
+ // Could not find error state
826
+ timeAndMedia.blink,
827
+ timeAndMedia.metaRefresh,
828
+ // Could not find error state
829
+ timeAndMedia.noAutoplayAudio
830
+ // Could not find error state
831
+ ],
832
+ /**
833
+ * These rules can't be resolved with a spread operator
834
+ * in the node's attributes
835
+ */
836
+ requiresAttrs: [
837
+ aria.ariaRequiredAttr,
838
+ language.htmlHasLang,
839
+ textAlternatives.areaAlt,
840
+ textAlternatives.imageAlt,
841
+ textAlternatives.imageRedundantAlt,
842
+ textAlternatives.inputImageAlt,
843
+ textAlternatives.objectAlt,
844
+ textAlternatives.roleImgAlt,
845
+ textAlternatives.svgImgAlt
846
+ ],
847
+ /**
848
+ * These rules can't be resolved with dynamic content
849
+ * in the body of the node
850
+ */
851
+ requiresChildren: [
852
+ aria.ariaRequiredChildren,
853
+ aria.ariaText,
854
+ aria.ariaValidAttrValue,
855
+ aria.emptyTableHeader,
856
+ keyboard.frameFocusableContent,
857
+ keyboard.skipLink,
858
+ nameRoleValue.ariaHiddenFocus,
859
+ semantics.labelContentNameMismatch,
860
+ structure.definitionList,
861
+ structure.list,
862
+ tables.tableDuplicateName,
863
+ tables.tableFakeCaption,
864
+ tables.thHasDataCells,
865
+ textAlternatives.documentTitle,
866
+ textAlternatives.frameTitleUnique,
867
+ textAlternatives.frameTitle,
868
+ textAlternatives.videoCaption,
869
+ timeAndMedia.audioCaption
870
+ ],
871
+ /**
872
+ * These rules can be resolved by changing content in
873
+ * either the node body or its attributes
874
+ */
875
+ requiresAttrsOrChildren: [
876
+ aria.ariaCommandName,
877
+ aria.ariaDialogName,
878
+ aria.ariaInputFieldName,
879
+ aria.ariaMeterName,
880
+ aria.ariaProgressbarName,
881
+ aria.ariaToggleFieldName,
882
+ aria.ariaTooltipName,
883
+ aria.ariaTreeitemName,
884
+ nameRoleValue.inputButtonName,
885
+ nameRoleValue.linkName
886
+ ],
887
+ /**
888
+ * These rules cannot be supported until multiple files
889
+ * are analyzed at once. For now they are ignored.
890
+ */
891
+ requiresParent: [
892
+ aria.ariaRequiredParent,
893
+ forms.label,
894
+ forms.labelTitleOnly,
895
+ forms.selectName,
896
+ keyboard.bypass,
897
+ keyboard.nestedInteractive,
898
+ keyboard.region,
899
+ semantics.headingOrder,
900
+ semantics.landmarkBannerIsTopLevel,
901
+ semantics.landmarkComplementaryIsTopLevel,
902
+ semantics.landmarkContentinfoIsTopLevel,
903
+ semantics.landmarkMainIsTopLevel,
904
+ semantics.landmarkOneMain,
905
+ semantics.pageHasHeadingOne,
906
+ structure.dlitem,
907
+ structure.listitem,
908
+ tables.tdHasHeader,
909
+ tables.tdHeadersAttr
910
+ ],
911
+ /**
912
+ * These rules should not be enforced to all users of
913
+ * the official Marko language server.
914
+ */
915
+ blacklist: [structure.frameTested, parsing.duplicateId],
916
+ /**
917
+ * These are rules that cannot currently be validated, either
918
+ * because of limitations with JSDom + axe-core or with the
919
+ * current implementation of the language server.
920
+ */
921
+ cannotValidate: [
922
+ keyboard.scrollableRegionFocusable,
923
+ semantics.pAsHeading,
924
+ structure.avoidInlineSpacing,
925
+ structure.cssOrientationLock,
926
+ structure.hiddenContent
927
+ ]
928
+ };
929
+ var separated_rules_default = rules;
930
+
931
+ // src/service/html/index.ts
932
+ var extractCache = /* @__PURE__ */ new WeakMap();
933
+ var HTMLService = {
934
+ commands: {
935
+ "$/showHtmlOutput": async (uri) => {
936
+ const doc = get(uri);
937
+ if (!doc)
938
+ return;
939
+ const { extracted } = extract(doc);
940
+ return {
941
+ language: "html",
942
+ content: extracted.toString()
943
+ };
944
+ }
945
+ },
946
+ async doValidate(doc) {
947
+ const { extracted, nodeDetails } = extract(doc);
948
+ const jsdom = new JSDOM(extracted.toString(), {
949
+ includeNodeLocations: true
950
+ });
951
+ const { documentElement } = jsdom.window.document;
952
+ const getViolationNodes = async (runOnly) => (await axe.run(documentElement, {
953
+ runOnly,
954
+ rules: {
955
+ "color-contrast": { enabled: false }
956
+ },
957
+ resultTypes: ["violations"],
958
+ elementRef: true
959
+ })).violations.flatMap(
960
+ ({ nodes, id }) => nodes.map((node) => ({ ...node, ruleId: id }))
961
+ );
962
+ const release = await acquireMutexLock();
963
+ const violations = await getViolationNodes(separated_rules_default.alwaysAllowed);
964
+ const requiresAttrs = await getViolationNodes(separated_rules_default.requiresAttrs);
965
+ const requiresChildren = await getViolationNodes(separated_rules_default.requiresChildren);
966
+ const requiresAttrsOrChildren = await getViolationNodes(
967
+ separated_rules_default.requiresAttrsOrChildren
968
+ );
969
+ release();
970
+ violations.push(
971
+ ...requiresAttrs.filter(
972
+ ({ element }) => (element == null ? void 0 : element.dataset.markoNodeId) && !nodeDetails[element.dataset.markoNodeId].hasDynamicAttrs
973
+ )
974
+ );
975
+ violations.push(
976
+ ...requiresChildren.filter(
977
+ ({ element }) => (element == null ? void 0 : element.dataset.markoNodeId) && !nodeDetails[element.dataset.markoNodeId].hasDynamicBody
978
+ )
979
+ );
980
+ violations.push(
981
+ ...requiresAttrsOrChildren.filter(
982
+ ({ element }) => (element == null ? void 0 : element.dataset.markoNodeId) && !nodeDetails[element.dataset.markoNodeId].hasDynamicAttrs && !nodeDetails[element.dataset.markoNodeId].hasDynamicBody
983
+ )
984
+ );
985
+ return violations.flatMap((result) => {
986
+ const { element } = result;
987
+ if (!element)
988
+ return [];
989
+ const generatedLoc = jsdom.nodeLocation(element);
990
+ if (!generatedLoc)
991
+ return [];
992
+ const sourceRange = extracted.sourceLocationAt(
993
+ generatedLoc.startOffset + 1,
994
+ generatedLoc.startOffset + 1 + element.tagName.length
995
+ );
996
+ if (!sourceRange)
997
+ return [];
998
+ return [
999
+ {
1000
+ range: sourceRange,
1001
+ severity: 3,
1002
+ source: `axe-core(${result.ruleId})`,
1003
+ message: result.failureSummary ?? "unknown accessibility issue"
1004
+ }
1005
+ ];
1006
+ });
1007
+ }
1008
+ };
1009
+ function extract(doc) {
1010
+ const { parsed } = getMarkoFile(doc);
1011
+ let cached = extractCache.get(parsed);
1012
+ if (!cached) {
1013
+ cached = extractHTML(parsed);
1014
+ extractCache.set(parsed, cached);
1015
+ }
1016
+ return cached;
1017
+ }
1018
+ var lock;
1019
+ async function acquireMutexLock() {
1020
+ const currLock = lock;
1021
+ let resolve;
1022
+ lock = new Promise((_) => resolve = _);
1023
+ await currLock;
1024
+ return resolve;
1025
+ }
1026
+ var html_default = HTMLService;
1027
+
279
1028
  // src/service/marko/complete/index.ts
280
1029
  import { NodeType as NodeType3 } from "@marko/language-tools";
281
1030
 
@@ -1289,7 +2038,7 @@ Project3.setDefaultTypePaths({
1289
2038
  internalTypesFile: path6.join(__dirname, "marko.internal.d.ts"),
1290
2039
  markoTypesFile: path6.join(__dirname, "marko.runtime.d.ts")
1291
2040
  });
1292
- function patch(ts2, configFile, extractCache2, resolutionCache, host, ps) {
2041
+ function patch(ts2, configFile, extractCache3, resolutionCache, host, ps) {
1293
2042
  var _a, _b, _c;
1294
2043
  const processors = Processors.create({
1295
2044
  ts: ts2,
@@ -1328,7 +2077,7 @@ function patch(ts2, configFile, extractCache2, resolutionCache, host, ps) {
1328
2077
  host.getScriptSnapshot = (fileName) => {
1329
2078
  const processor = getProcessor(fileName);
1330
2079
  if (processor) {
1331
- let cached = extractCache2.get(fileName);
2080
+ let cached = extractCache3.get(fileName);
1332
2081
  if (!cached) {
1333
2082
  const code = host.readFile(fileName, "utf-8") || "";
1334
2083
  try {
@@ -1338,7 +2087,7 @@ function patch(ts2, configFile, extractCache2, resolutionCache, host, ps) {
1338
2087
  cached = { snapshot: ts2.ScriptSnapshot.fromString("") };
1339
2088
  }
1340
2089
  trackFile(fileName);
1341
- extractCache2.set(fileName, cached);
2090
+ extractCache3.set(fileName, cached);
1342
2091
  }
1343
2092
  return cached.snapshot;
1344
2093
  }
@@ -1615,7 +2364,7 @@ function escapeBackTicks(text) {
1615
2364
 
1616
2365
  // src/service/script/index.ts
1617
2366
  var IGNORE_DIAG_REG = /^(?:(?:Expression|Identifier|['"][^\w]['"]) expected|Invalid character)\b/i;
1618
- var extractCache = /* @__PURE__ */ new Map();
2367
+ var extractCache2 = /* @__PURE__ */ new Map();
1619
2368
  var snapshotCache = /* @__PURE__ */ new Map();
1620
2369
  var insertModuleStatementLocCache = /* @__PURE__ */ new WeakMap();
1621
2370
  var markoFileReg = /\.marko$/;
@@ -1693,10 +2442,10 @@ var ScriptService = {
1693
2442
  onFileChange((doc) => {
1694
2443
  if (doc) {
1695
2444
  const filename = getFSPath(doc);
1696
- extractCache.delete(filename);
2445
+ extractCache2.delete(filename);
1697
2446
  snapshotCache.delete(filename);
1698
2447
  } else {
1699
- extractCache.clear();
2448
+ extractCache2.clear();
1700
2449
  snapshotCache.clear();
1701
2450
  }
1702
2451
  });
@@ -2158,7 +2907,7 @@ function getTSProject(docFsPath) {
2158
2907
  const host = patch(
2159
2908
  ts,
2160
2909
  configFile,
2161
- extractCache,
2910
+ extractCache2,
2162
2911
  resolutionCache,
2163
2912
  {
2164
2913
  getNewLine() {
@@ -2814,7 +3563,7 @@ function isTextEdit(edit) {
2814
3563
 
2815
3564
  // src/service/index.ts
2816
3565
  var REG_MARKDOWN_CHARS = /[\\`*_{}[\]<>()#+.!|-]/g;
2817
- var plugins = [marko_default, ScriptService, StyleSheetService];
3566
+ var plugins = [marko_default, ScriptService, StyleSheetService, html_default];
2818
3567
  var service = {
2819
3568
  commands: Object.assign({}, ...plugins.map(({ commands }) => commands)),
2820
3569
  async initialize(params) {
@@ -3157,7 +3906,7 @@ console.error = (...args) => {
3157
3906
  process.on("uncaughtException", console.error);
3158
3907
  process.on("unhandledRejection", console.error);
3159
3908
  connection3.onInitialize(async (params) => {
3160
- setup3(connection3);
3909
+ setup2(connection3);
3161
3910
  await service.initialize(params);
3162
3911
  return {
3163
3912
  capabilities: {
@@ -3199,9 +3948,23 @@ connection3.onInitialize(async (params) => {
3199
3948
  }
3200
3949
  };
3201
3950
  });
3202
- setup2(connection3);
3203
- onConfigChange(validateDocs);
3204
3951
  setup(connection3);
3952
+ onConfigChange(validateDocs);
3953
+ connection3.onDidOpenTextDocument(async (params) => {
3954
+ doOpen(params);
3955
+ const doc = get(params.textDocument.uri);
3956
+ if (doc) {
3957
+ const diagnostics = await service.doValidate(doc) || [];
3958
+ prevDiags.set(doc, diagnostics);
3959
+ connection3.sendDiagnostics({
3960
+ uri: doc.uri,
3961
+ diagnostics
3962
+ });
3963
+ }
3964
+ });
3965
+ connection3.onDidChangeTextDocument(doChange);
3966
+ connection3.onDidCloseTextDocument(doClose);
3967
+ connection3.onDidChangeWatchedFiles(doChangeWatchedFiles);
3205
3968
  onFileChange((changeDoc) => {
3206
3969
  if (changeDoc) {
3207
3970
  queueDiagnostic();