@astrojs/language-server 0.12.1 → 0.13.2
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/CHANGELOG.md +25 -0
- package/dist/core/documents/AstroDocument.d.ts +2 -2
- package/dist/core/documents/AstroDocument.js +6 -1
- package/dist/plugins/PluginHost.d.ts +2 -1
- package/dist/plugins/PluginHost.js +4 -0
- package/dist/plugins/css/CSSPlugin.d.ts +10 -1
- package/dist/plugins/css/CSSPlugin.js +62 -0
- package/dist/plugins/css/features/astro-selectors.js +2 -2
- package/dist/plugins/html/HTMLPlugin.d.ts +4 -1
- package/dist/plugins/html/HTMLPlugin.js +37 -1
- package/dist/plugins/html/features/astro-attributes.d.ts +2 -0
- package/dist/plugins/html/features/astro-attributes.js +126 -0
- package/dist/plugins/typescript/TypeScriptPlugin.d.ts +3 -1
- package/dist/plugins/typescript/TypeScriptPlugin.js +15 -0
- package/dist/plugins/typescript/features/CompletionsProvider.js +1 -1
- package/dist/plugins/typescript/features/DiagnosticsProvider.js +8 -29
- package/dist/plugins/typescript/features/DocumentSymbolsProvider.d.ts +10 -0
- package/dist/plugins/typescript/features/DocumentSymbolsProvider.js +69 -0
- package/dist/plugins/typescript/language-service.js +11 -3
- package/dist/plugins/typescript/snapshots/utils.js +1 -1
- package/dist/plugins/typescript/utils.d.ts +2 -1
- package/dist/plugins/typescript/utils.js +50 -1
- package/dist/server.js +2 -0
- package/dist/utils.d.ts +4 -8
- package/dist/utils.js +6 -10
- package/package.json +2 -2
- package/types/astro-jsx.d.ts +1077 -0
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,30 @@
|
|
|
1
1
|
# @astrojs/language-server
|
|
2
2
|
|
|
3
|
+
## 0.13.2
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- aff8b76: Fix error caused by malformed Svelte components
|
|
8
|
+
- Updated dependencies [aff8b76]
|
|
9
|
+
- @astrojs/svelte-language-integration@0.1.2
|
|
10
|
+
|
|
11
|
+
## 0.13.1
|
|
12
|
+
|
|
13
|
+
### Patch Changes
|
|
14
|
+
|
|
15
|
+
- ea74fdb: Publish failed
|
|
16
|
+
|
|
17
|
+
## 0.13.0
|
|
18
|
+
|
|
19
|
+
### Minor Changes
|
|
20
|
+
|
|
21
|
+
- 82b8891: Add HTML hover info, fix Astro directives producing errors, fix missing children property for JSX based frameworks
|
|
22
|
+
|
|
23
|
+
### Patch Changes
|
|
24
|
+
|
|
25
|
+
- 9f4f907: Add CSS hover info
|
|
26
|
+
- c09116f: Add support for Document Symbols (Outline tab, breadcrumb navigation)
|
|
27
|
+
|
|
3
28
|
## 0.12.1
|
|
4
29
|
|
|
5
30
|
### Patch Changes
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { HTMLDocument } from 'vscode-html-languageservice';
|
|
1
|
+
import { HTMLDocument, Range } from 'vscode-html-languageservice';
|
|
2
2
|
import { WritableDocument } from './DocumentBase';
|
|
3
3
|
import { AstroMetadata } from './parseAstro';
|
|
4
4
|
import { TagInformation } from './utils';
|
|
@@ -12,7 +12,7 @@ export declare class AstroDocument extends WritableDocument {
|
|
|
12
12
|
constructor(url: string, content: string);
|
|
13
13
|
private updateDocInfo;
|
|
14
14
|
setText(text: string): void;
|
|
15
|
-
getText(): string;
|
|
15
|
+
getText(range?: Range | undefined): string;
|
|
16
16
|
getURL(): string;
|
|
17
17
|
getFilePath(): string | null;
|
|
18
18
|
}
|
|
@@ -24,7 +24,12 @@ class AstroDocument extends DocumentBase_1.WritableDocument {
|
|
|
24
24
|
this.version++;
|
|
25
25
|
this.updateDocInfo();
|
|
26
26
|
}
|
|
27
|
-
getText() {
|
|
27
|
+
getText(range) {
|
|
28
|
+
if (range) {
|
|
29
|
+
const start = this.offsetAt(range.start);
|
|
30
|
+
const end = this.offsetAt(range.end);
|
|
31
|
+
return this.content.substring(start, end);
|
|
32
|
+
}
|
|
28
33
|
return this.content;
|
|
29
34
|
}
|
|
30
35
|
getURL() {
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { CancellationToken, Color, ColorInformation, ColorPresentation, CompletionContext, CompletionItem, CompletionList, DefinitionLink, Diagnostic, FoldingRange, Hover, Position, Range, Location, SignatureHelp, SignatureHelpContext, TextDocumentContentChangeEvent, TextDocumentIdentifier, WorkspaceEdit } from 'vscode-languageserver';
|
|
1
|
+
import { CancellationToken, Color, ColorInformation, ColorPresentation, CompletionContext, CompletionItem, CompletionList, DefinitionLink, Diagnostic, FoldingRange, Hover, Position, Range, Location, SignatureHelp, SignatureHelpContext, TextDocumentContentChangeEvent, TextDocumentIdentifier, WorkspaceEdit, SymbolInformation } from 'vscode-languageserver';
|
|
2
2
|
import type { AppCompletionItem, Plugin } from './interfaces';
|
|
3
3
|
import { DocumentManager } from '../core/documents/DocumentManager';
|
|
4
4
|
interface PluginHostConfig {
|
|
@@ -18,6 +18,7 @@ export declare class PluginHost {
|
|
|
18
18
|
doHover(textDocument: TextDocumentIdentifier, position: Position): Promise<Hover | null>;
|
|
19
19
|
doTagComplete(textDocument: TextDocumentIdentifier, position: Position): Promise<string | null>;
|
|
20
20
|
getFoldingRanges(textDocument: TextDocumentIdentifier): Promise<FoldingRange[] | null>;
|
|
21
|
+
getDocumentSymbols(textDocument: TextDocumentIdentifier, cancellationToken: CancellationToken): Promise<SymbolInformation[]>;
|
|
21
22
|
getDefinitions(textDocument: TextDocumentIdentifier, position: Position): Promise<DefinitionLink[] | Location[]>;
|
|
22
23
|
rename(textDocument: TextDocumentIdentifier, position: Position, newName: string): Promise<WorkspaceEdit | null>;
|
|
23
24
|
getDocumentColors(textDocument: TextDocumentIdentifier): Promise<ColorInformation[]>;
|
|
@@ -53,6 +53,10 @@ class PluginHost {
|
|
|
53
53
|
const foldingRanges = (0, lodash_1.flatten)(await this.execute('getFoldingRanges', [document], ExecuteMode.Collect)).filter((completion) => completion != null);
|
|
54
54
|
return foldingRanges;
|
|
55
55
|
}
|
|
56
|
+
async getDocumentSymbols(textDocument, cancellationToken) {
|
|
57
|
+
const document = this.getDocument(textDocument.uri);
|
|
58
|
+
return (0, lodash_1.flatten)(await this.execute('getDocumentSymbols', [document, cancellationToken], ExecuteMode.Collect));
|
|
59
|
+
}
|
|
56
60
|
async getDefinitions(textDocument, position) {
|
|
57
61
|
const document = this.getDocument(textDocument.uri);
|
|
58
62
|
const definitions = (0, lodash_1.flatten)(await this.execute('getDefinitions', [document, position], ExecuteMode.Collect));
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Color, ColorInformation, ColorPresentation, CompletionContext, CompletionList, Position, Range } from 'vscode-languageserver';
|
|
1
|
+
import { Color, ColorInformation, ColorPresentation, CompletionContext, CompletionList, Hover, Position, Range, SymbolInformation } from 'vscode-languageserver';
|
|
2
2
|
import { ConfigManager } from '../../core/config/ConfigManager';
|
|
3
3
|
import { AstroDocument } from '../../core/documents';
|
|
4
4
|
import type { Plugin } from '../interfaces';
|
|
@@ -8,16 +8,25 @@ export declare class CSSPlugin implements Plugin {
|
|
|
8
8
|
private cssDocuments;
|
|
9
9
|
private triggerCharacters;
|
|
10
10
|
constructor(configManager: ConfigManager);
|
|
11
|
+
doHover(document: AstroDocument, position: Position): Hover | null;
|
|
12
|
+
private doHoverInternal;
|
|
11
13
|
getCompletions(document: AstroDocument, position: Position, completionContext?: CompletionContext): CompletionList | null;
|
|
12
14
|
private getCompletionsInternal;
|
|
13
15
|
getDocumentColors(document: AstroDocument): ColorInformation[];
|
|
14
16
|
getColorPresentations(document: AstroDocument, range: Range, color: Color): ColorPresentation[];
|
|
17
|
+
getDocumentSymbols(document: AstroDocument): SymbolInformation[];
|
|
15
18
|
private inStyleAttributeWithoutInterpolation;
|
|
16
19
|
/**
|
|
17
20
|
* Get the associated CSS Document for a style tag
|
|
18
21
|
*/
|
|
19
22
|
private getCSSDocumentForStyleTag;
|
|
23
|
+
/**
|
|
24
|
+
* Get all the CSSDocuments in a document
|
|
25
|
+
*/
|
|
20
26
|
private getCSSDocumentsForDocument;
|
|
27
|
+
/**
|
|
28
|
+
* Get all the stylesheets (Stylesheet type) in a document
|
|
29
|
+
*/
|
|
21
30
|
private getStylesheetsForDocument;
|
|
22
31
|
/**
|
|
23
32
|
* Get style tag at position for a document
|
|
@@ -17,6 +17,35 @@ class CSSPlugin {
|
|
|
17
17
|
this.triggerCharacters = new Set(['.', ':', '-', '/']);
|
|
18
18
|
this.configManager = configManager;
|
|
19
19
|
}
|
|
20
|
+
doHover(document, position) {
|
|
21
|
+
if (!this.featureEnabled('hover')) {
|
|
22
|
+
return null;
|
|
23
|
+
}
|
|
24
|
+
if ((0, documents_1.isInsideFrontmatter)(document.getText(), document.offsetAt(position))) {
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
const styleTag = this.getStyleTagForPosition(document, position);
|
|
28
|
+
if (!styleTag) {
|
|
29
|
+
const attributeContext = (0, parseHtml_1.getAttributeContextAtPosition)(document, position);
|
|
30
|
+
if (!attributeContext) {
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
if (this.inStyleAttributeWithoutInterpolation(attributeContext, document.getText())) {
|
|
34
|
+
const [start, end] = attributeContext.valueRange;
|
|
35
|
+
return this.doHoverInternal(new StyleAttributeDocument_1.StyleAttributeDocument(document, start, end), position);
|
|
36
|
+
}
|
|
37
|
+
return null;
|
|
38
|
+
}
|
|
39
|
+
const cssDocument = this.getCSSDocumentForStyleTag(styleTag, document);
|
|
40
|
+
if (shouldExcludeHover(cssDocument)) {
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
return this.doHoverInternal(cssDocument, position);
|
|
44
|
+
}
|
|
45
|
+
doHoverInternal(cssDocument, position) {
|
|
46
|
+
const hoverInfo = (0, language_service_1.getLanguageService)(extractLanguage(cssDocument)).doHover(cssDocument, cssDocument.getGeneratedPosition(position), cssDocument.stylesheet);
|
|
47
|
+
return hoverInfo ? (0, documents_1.mapHoverToParent)(cssDocument, hoverInfo) : hoverInfo;
|
|
48
|
+
}
|
|
20
49
|
getCompletions(document, position, completionContext) {
|
|
21
50
|
if (!this.featureEnabled('completions')) {
|
|
22
51
|
return null;
|
|
@@ -100,6 +129,17 @@ class CSSPlugin {
|
|
|
100
129
|
});
|
|
101
130
|
return (0, lodash_1.flatten)(allColorPres);
|
|
102
131
|
}
|
|
132
|
+
getDocumentSymbols(document) {
|
|
133
|
+
if (!this.featureEnabled('documentSymbols')) {
|
|
134
|
+
return [];
|
|
135
|
+
}
|
|
136
|
+
const allDocumentSymbols = this.getCSSDocumentsForDocument(document).map((cssDoc) => {
|
|
137
|
+
return (0, language_service_1.getLanguageService)(extractLanguage(cssDoc))
|
|
138
|
+
.findDocumentSymbols(cssDoc, cssDoc.stylesheet)
|
|
139
|
+
.map((symbol) => (0, documents_1.mapSymbolInformationToOriginal)(cssDoc, symbol));
|
|
140
|
+
});
|
|
141
|
+
return (0, lodash_1.flatten)(allDocumentSymbols);
|
|
142
|
+
}
|
|
103
143
|
inStyleAttributeWithoutInterpolation(attrContext, text) {
|
|
104
144
|
return (attrContext.name === 'style' &&
|
|
105
145
|
!!attrContext.valueRange &&
|
|
@@ -116,9 +156,15 @@ class CSSPlugin {
|
|
|
116
156
|
}
|
|
117
157
|
return cssDoc;
|
|
118
158
|
}
|
|
159
|
+
/**
|
|
160
|
+
* Get all the CSSDocuments in a document
|
|
161
|
+
*/
|
|
119
162
|
getCSSDocumentsForDocument(document) {
|
|
120
163
|
return document.styleTags.map((tag) => this.getCSSDocumentForStyleTag(tag, document));
|
|
121
164
|
}
|
|
165
|
+
/**
|
|
166
|
+
* Get all the stylesheets (Stylesheet type) in a document
|
|
167
|
+
*/
|
|
122
168
|
getStylesheetsForDocument(document) {
|
|
123
169
|
return this.getCSSDocumentsForDocument(document).map((cssDoc) => cssDoc.stylesheet);
|
|
124
170
|
}
|
|
@@ -135,6 +181,22 @@ class CSSPlugin {
|
|
|
135
181
|
}
|
|
136
182
|
}
|
|
137
183
|
exports.CSSPlugin = CSSPlugin;
|
|
184
|
+
/**
|
|
185
|
+
* Exclude certain language when getting hover info
|
|
186
|
+
* The CSS language service only supports CSS, LESS and SCSS,
|
|
187
|
+
* which mean that we cannot support hover info in other languages
|
|
188
|
+
*/
|
|
189
|
+
function shouldExcludeHover(document) {
|
|
190
|
+
const language = typeof document === 'string' ? document : extractLanguage(document);
|
|
191
|
+
switch (language) {
|
|
192
|
+
case 'sass':
|
|
193
|
+
case 'stylus':
|
|
194
|
+
case 'styl':
|
|
195
|
+
return true;
|
|
196
|
+
default:
|
|
197
|
+
return false;
|
|
198
|
+
}
|
|
199
|
+
}
|
|
138
200
|
/**
|
|
139
201
|
* Exclude certain language when getting colors
|
|
140
202
|
* The CSS language service only supports CSS, LESS and SCSS,
|
|
@@ -5,10 +5,10 @@ exports.pseudoClass = [
|
|
|
5
5
|
{
|
|
6
6
|
name: ':global()',
|
|
7
7
|
description: `[astro] :global modifier
|
|
8
|
-
|
|
8
|
+
Apply styles to a selector globally`,
|
|
9
9
|
references: [
|
|
10
10
|
{
|
|
11
|
-
name: 'Astro
|
|
11
|
+
name: 'Astro documentation',
|
|
12
12
|
url: 'https://docs.astro.build/en/guides/styling/#global-styles-within-style-tag',
|
|
13
13
|
},
|
|
14
14
|
],
|
|
@@ -1,19 +1,22 @@
|
|
|
1
|
-
import { CompletionList, Position, FoldingRange } from 'vscode-languageserver';
|
|
1
|
+
import { CompletionList, Position, FoldingRange, Hover, SymbolInformation } from 'vscode-languageserver';
|
|
2
2
|
import type { Plugin } from '../interfaces';
|
|
3
3
|
import { ConfigManager } from '../../core/config/ConfigManager';
|
|
4
4
|
import { AstroDocument } from '../../core/documents/AstroDocument';
|
|
5
5
|
export declare class HTMLPlugin implements Plugin {
|
|
6
6
|
__name: string;
|
|
7
7
|
private lang;
|
|
8
|
+
private componentLang;
|
|
8
9
|
private styleScriptTemplate;
|
|
9
10
|
private configManager;
|
|
10
11
|
constructor(configManager: ConfigManager);
|
|
12
|
+
doHover(document: AstroDocument, position: Position): Hover | null;
|
|
11
13
|
/**
|
|
12
14
|
* Get HTML completions
|
|
13
15
|
*/
|
|
14
16
|
getCompletions(document: AstroDocument, position: Position): CompletionList | null;
|
|
15
17
|
getFoldingRanges(document: AstroDocument): FoldingRange[] | null;
|
|
16
18
|
doTagComplete(document: AstroDocument, position: Position): string | null;
|
|
19
|
+
getDocumentSymbols(document: AstroDocument): SymbolInformation[];
|
|
17
20
|
/**
|
|
18
21
|
* Get lang completions for style tags (ex: `<style lang="scss">`)
|
|
19
22
|
*/
|
|
@@ -5,13 +5,39 @@ const vscode_languageserver_1 = require("vscode-languageserver");
|
|
|
5
5
|
const emmet_helper_1 = require("@vscode/emmet-helper");
|
|
6
6
|
const vscode_html_languageservice_1 = require("vscode-html-languageservice");
|
|
7
7
|
const utils_1 = require("../../core/documents/utils");
|
|
8
|
+
const utils_2 = require("../../utils");
|
|
9
|
+
const astro_attributes_1 = require("./features/astro-attributes");
|
|
8
10
|
class HTMLPlugin {
|
|
9
11
|
constructor(configManager) {
|
|
10
12
|
this.__name = 'html';
|
|
11
|
-
this.lang = (0, vscode_html_languageservice_1.getLanguageService)(
|
|
13
|
+
this.lang = (0, vscode_html_languageservice_1.getLanguageService)({
|
|
14
|
+
customDataProviders: [astro_attributes_1.astroAttributes],
|
|
15
|
+
});
|
|
16
|
+
this.componentLang = (0, vscode_html_languageservice_1.getLanguageService)({
|
|
17
|
+
customDataProviders: [astro_attributes_1.astroAttributes, astro_attributes_1.astroDirectives],
|
|
18
|
+
useDefaultDataProvider: false,
|
|
19
|
+
});
|
|
12
20
|
this.styleScriptTemplate = new Set(['style']);
|
|
13
21
|
this.configManager = configManager;
|
|
14
22
|
}
|
|
23
|
+
doHover(document, position) {
|
|
24
|
+
if (!this.featureEnabled('hover')) {
|
|
25
|
+
return null;
|
|
26
|
+
}
|
|
27
|
+
const html = document.html;
|
|
28
|
+
if (!html) {
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
const node = html.findNodeAt(document.offsetAt(position));
|
|
32
|
+
if (!node) {
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
// If the node we're hovering on is a component, instead only provide astro-specific hover info
|
|
36
|
+
if ((0, utils_2.isPossibleComponent)(node)) {
|
|
37
|
+
return this.componentLang.doHover(document, position, html);
|
|
38
|
+
}
|
|
39
|
+
return this.lang.doHover(document, position, html);
|
|
40
|
+
}
|
|
15
41
|
/**
|
|
16
42
|
* Get HTML completions
|
|
17
43
|
*/
|
|
@@ -66,6 +92,16 @@ class HTMLPlugin {
|
|
|
66
92
|
}
|
|
67
93
|
return this.lang.doTagComplete(document, position, html);
|
|
68
94
|
}
|
|
95
|
+
getDocumentSymbols(document) {
|
|
96
|
+
if (!this.featureEnabled('documentSymbols')) {
|
|
97
|
+
return [];
|
|
98
|
+
}
|
|
99
|
+
const html = document.html;
|
|
100
|
+
if (!html) {
|
|
101
|
+
return [];
|
|
102
|
+
}
|
|
103
|
+
return this.lang.findDocumentSymbols(document, html);
|
|
104
|
+
}
|
|
69
105
|
/**
|
|
70
106
|
* Get lang completions for style tags (ex: `<style lang="scss">`)
|
|
71
107
|
*/
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.astroDirectives = exports.astroAttributes = void 0;
|
|
4
|
+
const vscode_html_languageservice_1 = require("vscode-html-languageservice");
|
|
5
|
+
exports.astroAttributes = (0, vscode_html_languageservice_1.newHTMLDataProvider)('astro-attributes', {
|
|
6
|
+
version: 1,
|
|
7
|
+
globalAttributes: [
|
|
8
|
+
{
|
|
9
|
+
name: 'class:list',
|
|
10
|
+
description: 'Utility to provide a list of class',
|
|
11
|
+
},
|
|
12
|
+
{
|
|
13
|
+
name: 'set:html',
|
|
14
|
+
description: 'Inject unescaped HTML into this tag',
|
|
15
|
+
references: [
|
|
16
|
+
{
|
|
17
|
+
name: 'Astro documentation',
|
|
18
|
+
url: 'https://docs.astro.build/en/migrate/#deprecated-unescaped-html',
|
|
19
|
+
},
|
|
20
|
+
],
|
|
21
|
+
},
|
|
22
|
+
{
|
|
23
|
+
name: 'set:text',
|
|
24
|
+
description: 'Inject escaped text into this tag',
|
|
25
|
+
references: [
|
|
26
|
+
{
|
|
27
|
+
name: 'Astro documentation',
|
|
28
|
+
url: 'https://docs.astro.build/en/migrate/#deprecated-unescaped-html',
|
|
29
|
+
},
|
|
30
|
+
],
|
|
31
|
+
},
|
|
32
|
+
],
|
|
33
|
+
tags: [
|
|
34
|
+
{
|
|
35
|
+
name: 'script',
|
|
36
|
+
attributes: [
|
|
37
|
+
{
|
|
38
|
+
// The VS Code tag definitions does not provide a description for the deprecated `charset` attribute on script tags
|
|
39
|
+
// Which mean that since we get no hover info for this, we instead get JSX hover info. So we'll just specify a description ourselves for this specific case
|
|
40
|
+
name: 'charset',
|
|
41
|
+
description: "(Deprecated) It's unnecessary to specify the charset attribute, because documents must use UTF-8, and the script element inherits its character encoding from the document.",
|
|
42
|
+
},
|
|
43
|
+
{
|
|
44
|
+
name: 'define:vars',
|
|
45
|
+
description: 'Passes serializable server-side variables into a client-side script element',
|
|
46
|
+
references: [
|
|
47
|
+
{
|
|
48
|
+
name: 'Astro documentation',
|
|
49
|
+
url: 'https://docs.astro.build/en/guides/styling/#variables-in-scripts--styles',
|
|
50
|
+
},
|
|
51
|
+
],
|
|
52
|
+
},
|
|
53
|
+
],
|
|
54
|
+
},
|
|
55
|
+
{
|
|
56
|
+
name: 'style',
|
|
57
|
+
attributes: [
|
|
58
|
+
{
|
|
59
|
+
name: 'define:vars',
|
|
60
|
+
description: 'Passes serializable server-side variables into a client-side style element',
|
|
61
|
+
references: [
|
|
62
|
+
{
|
|
63
|
+
name: 'Astro documentation',
|
|
64
|
+
url: 'https://docs.astro.build/en/guides/styling/#variables-in-scripts--styles',
|
|
65
|
+
},
|
|
66
|
+
],
|
|
67
|
+
},
|
|
68
|
+
],
|
|
69
|
+
},
|
|
70
|
+
],
|
|
71
|
+
});
|
|
72
|
+
exports.astroDirectives = (0, vscode_html_languageservice_1.newHTMLDataProvider)('astro-directives', {
|
|
73
|
+
version: 1,
|
|
74
|
+
globalAttributes: [
|
|
75
|
+
{
|
|
76
|
+
name: 'client:load',
|
|
77
|
+
description: 'Start importing the component JS at page load. Hydrate the component when import completes.',
|
|
78
|
+
references: [
|
|
79
|
+
{
|
|
80
|
+
name: 'Astro documentation',
|
|
81
|
+
url: 'https://docs.astro.build/en/core-concepts/component-hydration/#hydrate-interactive-components',
|
|
82
|
+
},
|
|
83
|
+
],
|
|
84
|
+
},
|
|
85
|
+
{
|
|
86
|
+
name: 'client:idle',
|
|
87
|
+
description: 'Start importing the component JS as soon as main thread is free (uses requestIdleCallback()). Hydrate the component when import completes.',
|
|
88
|
+
references: [
|
|
89
|
+
{
|
|
90
|
+
name: 'Astro documentation',
|
|
91
|
+
url: 'https://docs.astro.build/en/core-concepts/component-hydration/#hydrate-interactive-components',
|
|
92
|
+
},
|
|
93
|
+
],
|
|
94
|
+
},
|
|
95
|
+
{
|
|
96
|
+
name: 'client:visible',
|
|
97
|
+
description: 'Start importing the component JS as soon as the element enters the viewport (uses IntersectionObserver). Hydrate the component when import completes. Useful for content lower down on the page.',
|
|
98
|
+
references: [
|
|
99
|
+
{
|
|
100
|
+
name: 'Astro documentation',
|
|
101
|
+
url: 'https://docs.astro.build/en/core-concepts/component-hydration/#hydrate-interactive-components',
|
|
102
|
+
},
|
|
103
|
+
],
|
|
104
|
+
},
|
|
105
|
+
{
|
|
106
|
+
name: 'client:media',
|
|
107
|
+
description: 'Start importing the component JS as soon as the browser matches the given media query (uses matchMedia). Hydrate the component when import completes. Useful for sidebar toggles, or other elements that should only display on mobile or desktop devices.',
|
|
108
|
+
references: [
|
|
109
|
+
{
|
|
110
|
+
name: 'Astro documentation',
|
|
111
|
+
url: 'https://docs.astro.build/en/core-concepts/component-hydration/#hydrate-interactive-components',
|
|
112
|
+
},
|
|
113
|
+
],
|
|
114
|
+
},
|
|
115
|
+
{
|
|
116
|
+
name: 'client:only',
|
|
117
|
+
description: 'Start importing the component JS at page load and hydrate when the import completes, similar to client:load. The component will be skipped at build time, useful for components that are entirely dependent on client-side APIs. This is best avoided unless absolutely needed, in most cases it is best to render placeholder content on the server and delay any browser API calls until the component hydrates in the browser.',
|
|
118
|
+
references: [
|
|
119
|
+
{
|
|
120
|
+
name: 'Astro documentation',
|
|
121
|
+
url: 'https://docs.astro.build/en/core-concepts/component-hydration/#hydrate-interactive-components',
|
|
122
|
+
},
|
|
123
|
+
],
|
|
124
|
+
},
|
|
125
|
+
],
|
|
126
|
+
});
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { CancellationToken, CompletionContext, DefinitionLink, Diagnostic, Hover, Position, SignatureHelp, SignatureHelpContext, TextDocumentContentChangeEvent, WorkspaceEdit } from 'vscode-languageserver';
|
|
1
|
+
import { CancellationToken, CompletionContext, DefinitionLink, Diagnostic, Hover, Position, SignatureHelp, SignatureHelpContext, SymbolInformation, TextDocumentContentChangeEvent, WorkspaceEdit } from 'vscode-languageserver';
|
|
2
2
|
import { ConfigManager } from '../../core/config';
|
|
3
3
|
import { AstroDocument, DocumentManager } from '../../core/documents';
|
|
4
4
|
import { AppCompletionItem, AppCompletionList, OnWatchFileChangesParam, Plugin } from '../interfaces';
|
|
@@ -11,9 +11,11 @@ export declare class TypeScriptPlugin implements Plugin {
|
|
|
11
11
|
private readonly hoverProvider;
|
|
12
12
|
private readonly signatureHelpProvider;
|
|
13
13
|
private readonly diagnosticsProvider;
|
|
14
|
+
private readonly documentSymbolsProvider;
|
|
14
15
|
constructor(docManager: DocumentManager, configManager: ConfigManager, workspaceUris: string[]);
|
|
15
16
|
doHover(document: AstroDocument, position: Position): Promise<Hover | null>;
|
|
16
17
|
rename(document: AstroDocument, position: Position, newName: string): Promise<WorkspaceEdit | null>;
|
|
18
|
+
getDocumentSymbols(document: AstroDocument): Promise<SymbolInformation[]>;
|
|
17
19
|
getCompletions(document: AstroDocument, position: Position, completionContext?: CompletionContext): Promise<AppCompletionList<CompletionEntryWithIdentifer> | null>;
|
|
18
20
|
resolveCompletion(document: AstroDocument, completionItem: AppCompletionItem<CompletionEntryWithIdentifer>): Promise<AppCompletionItem<CompletionEntryWithIdentifer>>;
|
|
19
21
|
getDefinitions(document: AstroDocument, position: Position): Promise<DefinitionLink[]>;
|
|
@@ -35,6 +35,7 @@ const SignatureHelpProvider_1 = require("./features/SignatureHelpProvider");
|
|
|
35
35
|
const utils_2 = require("./features/utils");
|
|
36
36
|
const LanguageServiceManager_1 = require("./LanguageServiceManager");
|
|
37
37
|
const utils_3 = require("./utils");
|
|
38
|
+
const DocumentSymbolsProvider_1 = require("./features/DocumentSymbolsProvider");
|
|
38
39
|
class TypeScriptPlugin {
|
|
39
40
|
constructor(docManager, configManager, workspaceUris) {
|
|
40
41
|
this.__name = 'typescript';
|
|
@@ -44,8 +45,12 @@ class TypeScriptPlugin {
|
|
|
44
45
|
this.hoverProvider = new HoverProvider_1.HoverProviderImpl(this.languageServiceManager);
|
|
45
46
|
this.signatureHelpProvider = new SignatureHelpProvider_1.SignatureHelpProviderImpl(this.languageServiceManager);
|
|
46
47
|
this.diagnosticsProvider = new DiagnosticsProvider_1.DiagnosticsProviderImpl(this.languageServiceManager);
|
|
48
|
+
this.documentSymbolsProvider = new DocumentSymbolsProvider_1.DocumentSymbolsProviderImpl(this.languageServiceManager);
|
|
47
49
|
}
|
|
48
50
|
async doHover(document, position) {
|
|
51
|
+
if (!this.featureEnabled('hover')) {
|
|
52
|
+
return null;
|
|
53
|
+
}
|
|
49
54
|
return this.hoverProvider.doHover(document, position);
|
|
50
55
|
}
|
|
51
56
|
async rename(document, position, newName) {
|
|
@@ -71,7 +76,17 @@ class TypeScriptPlugin {
|
|
|
71
76
|
});
|
|
72
77
|
return edit;
|
|
73
78
|
}
|
|
79
|
+
async getDocumentSymbols(document) {
|
|
80
|
+
if (!this.featureEnabled('documentSymbols')) {
|
|
81
|
+
return [];
|
|
82
|
+
}
|
|
83
|
+
const symbols = await this.documentSymbolsProvider.getDocumentSymbols(document);
|
|
84
|
+
return symbols;
|
|
85
|
+
}
|
|
74
86
|
async getCompletions(document, position, completionContext) {
|
|
87
|
+
if (!this.featureEnabled('completions')) {
|
|
88
|
+
return null;
|
|
89
|
+
}
|
|
75
90
|
const completions = await this.completionProvider.getCompletions(document, position, completionContext);
|
|
76
91
|
return completions;
|
|
77
92
|
}
|
|
@@ -19,7 +19,7 @@ class CompletionsProviderImpl {
|
|
|
19
19
|
}
|
|
20
20
|
async getCompletions(document, position, _completionContext) {
|
|
21
21
|
var _a;
|
|
22
|
-
// TODO: handle inside expression
|
|
22
|
+
// TODO: handle inside expression and script tags
|
|
23
23
|
if (!(0, utils_1.isInsideFrontmatter)(document.getText(), document.offsetAt(position))) {
|
|
24
24
|
return null;
|
|
25
25
|
}
|
|
@@ -188,35 +188,14 @@ function isNoMarkdownBlockQuoteWithinMarkdown(sourceFile, boundaries, diagnostic
|
|
|
188
188
|
* Some diagnostics have JSX-specific nomenclature. Enhance them for more clarity.
|
|
189
189
|
*/
|
|
190
190
|
function enhanceIfNecessary(diagnostic) {
|
|
191
|
-
if (diagnostic.code ===
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
'If you are using Svelte 3.31+, use SvelteComponentTyped:\n' +
|
|
200
|
-
' import type { SvelteComponentTyped } from "svelte";\n' +
|
|
201
|
-
' class ComponentName extends SvelteComponentTyped<{propertyName: string;}> {}\n\n' +
|
|
202
|
-
'Underlying error:\n' +
|
|
203
|
-
diagnostic.message,
|
|
204
|
-
};
|
|
205
|
-
}
|
|
206
|
-
if (diagnostic.code === 2607) {
|
|
207
|
-
return {
|
|
208
|
-
...diagnostic,
|
|
209
|
-
message: 'Element does not support attributes because ' +
|
|
210
|
-
'type definitions are missing for this Svelte Component or element cannot be used as such.\n\n' +
|
|
211
|
-
'Underlying error:\n' +
|
|
212
|
-
diagnostic.message,
|
|
213
|
-
};
|
|
214
|
-
}
|
|
215
|
-
if (diagnostic.code === 1184) {
|
|
216
|
-
return {
|
|
217
|
-
...diagnostic,
|
|
218
|
-
message: diagnostic.message + '\nIf this is a declare statement, move it into <script context="module">..</script>',
|
|
219
|
-
};
|
|
191
|
+
if (diagnostic.code === 2322) {
|
|
192
|
+
// For the rare case where an user might try to put a client directive on something that is not a component
|
|
193
|
+
if (diagnostic.message.includes("Property 'client:") && diagnostic.message.includes("to type 'HTMLProps")) {
|
|
194
|
+
return {
|
|
195
|
+
...diagnostic,
|
|
196
|
+
message: 'Client directives are only available on framework components',
|
|
197
|
+
};
|
|
198
|
+
}
|
|
220
199
|
}
|
|
221
200
|
return diagnostic;
|
|
222
201
|
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { SymbolInformation } from 'vscode-languageserver-types';
|
|
2
|
+
import { AstroDocument } from '../../../core/documents';
|
|
3
|
+
import { DocumentSymbolsProvider } from '../../interfaces';
|
|
4
|
+
import { LanguageServiceManager } from '../LanguageServiceManager';
|
|
5
|
+
export declare class DocumentSymbolsProviderImpl implements DocumentSymbolsProvider {
|
|
6
|
+
private languageServiceManager;
|
|
7
|
+
constructor(languageServiceManager: LanguageServiceManager);
|
|
8
|
+
getDocumentSymbols(document: AstroDocument): Promise<SymbolInformation[]>;
|
|
9
|
+
private collectSymbols;
|
|
10
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.DocumentSymbolsProviderImpl = void 0;
|
|
4
|
+
const typescript_1 = require("typescript");
|
|
5
|
+
const vscode_languageserver_types_1 = require("vscode-languageserver-types");
|
|
6
|
+
const documents_1 = require("../../../core/documents");
|
|
7
|
+
const utils_1 = require("../utils");
|
|
8
|
+
const vscode_languageserver_types_2 = require("vscode-languageserver-types");
|
|
9
|
+
class DocumentSymbolsProviderImpl {
|
|
10
|
+
constructor(languageServiceManager) {
|
|
11
|
+
this.languageServiceManager = languageServiceManager;
|
|
12
|
+
}
|
|
13
|
+
async getDocumentSymbols(document) {
|
|
14
|
+
var _a, _b, _c;
|
|
15
|
+
const { lang, tsDoc } = await this.languageServiceManager.getLSAndTSDoc(document);
|
|
16
|
+
const fragment = await tsDoc.createFragment();
|
|
17
|
+
const navTree = lang.getNavigationTree(tsDoc.filePath);
|
|
18
|
+
if (!navTree) {
|
|
19
|
+
return [];
|
|
20
|
+
}
|
|
21
|
+
const symbols = [];
|
|
22
|
+
this.collectSymbols(navTree, fragment, undefined, (symbol) => symbols.push(symbol));
|
|
23
|
+
const result = [];
|
|
24
|
+
// Add a "Frontmatter" namespace for the frontmatter if we have a closed one
|
|
25
|
+
if (document.astroMeta.frontmatter.state === 'closed') {
|
|
26
|
+
result.push(vscode_languageserver_types_1.SymbolInformation.create('Frontmatter', vscode_languageserver_types_1.SymbolKind.Namespace, vscode_languageserver_types_1.Range.create(document.positionAt(document.astroMeta.frontmatter.startOffset), document.positionAt(document.astroMeta.frontmatter.endOffset))));
|
|
27
|
+
}
|
|
28
|
+
// Add a "Template" namespace for everything under the frontmatter
|
|
29
|
+
result.push(vscode_languageserver_types_1.SymbolInformation.create('Template', vscode_languageserver_types_1.SymbolKind.Namespace, vscode_languageserver_types_1.Range.create(document.positionAt((_a = document.astroMeta.frontmatter.endOffset) !== null && _a !== void 0 ? _a : 0), document.positionAt(document.getTextLength()))));
|
|
30
|
+
for (let symbol of symbols.splice(1)) {
|
|
31
|
+
symbol = (0, documents_1.mapSymbolInformationToOriginal)(fragment, symbol);
|
|
32
|
+
if (document.offsetAt(symbol.location.range.end) >= ((_b = document.astroMeta.content.firstNonWhitespaceOffset) !== null && _b !== void 0 ? _b : 0)) {
|
|
33
|
+
symbol.containerName = 'Template';
|
|
34
|
+
// For some reason, it seems like TypeScript thinks that the "class" attribute is a real class, weird
|
|
35
|
+
if (symbol.kind === vscode_languageserver_types_1.SymbolKind.Class && symbol.name === '<class>') {
|
|
36
|
+
const node = document.html.findNodeAt(document.offsetAt(symbol.location.range.start));
|
|
37
|
+
if ((_c = node.attributes) === null || _c === void 0 ? void 0 : _c.class) {
|
|
38
|
+
continue;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
// Remove the default function detected in our TSX output
|
|
43
|
+
if (symbol.kind === vscode_languageserver_types_1.SymbolKind.Function && symbol.name == 'default') {
|
|
44
|
+
continue;
|
|
45
|
+
}
|
|
46
|
+
result.push(symbol);
|
|
47
|
+
}
|
|
48
|
+
return result;
|
|
49
|
+
}
|
|
50
|
+
collectSymbols(item, fragment, container, cb) {
|
|
51
|
+
for (const span of item.spans) {
|
|
52
|
+
const symbol = vscode_languageserver_types_1.SymbolInformation.create(item.text, (0, utils_1.symbolKindFromString)(item.kind), vscode_languageserver_types_1.Range.create(fragment.positionAt(span.start), fragment.positionAt(span.start + span.length)), fragment.getURL(), container);
|
|
53
|
+
// TypeScript gives us kind modifiers as a string instead of an array
|
|
54
|
+
const kindModifiers = new Set(item.kindModifiers.split(/,|\s+/g));
|
|
55
|
+
if (kindModifiers.has(typescript_1.ScriptElementKindModifier.deprecatedModifier)) {
|
|
56
|
+
if (!symbol.tags)
|
|
57
|
+
symbol.tags = [];
|
|
58
|
+
symbol.tags.push(vscode_languageserver_types_2.SymbolTag.Deprecated);
|
|
59
|
+
}
|
|
60
|
+
cb(symbol);
|
|
61
|
+
}
|
|
62
|
+
if (item.childItems) {
|
|
63
|
+
for (const child of item.childItems) {
|
|
64
|
+
this.collectSymbols(child, fragment, item.text, cb);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
exports.DocumentSymbolsProviderImpl = DocumentSymbolsProviderImpl;
|