diff options
Diffstat (limited to 'tools/astro-languageserver/src/plugins')
6 files changed, 231 insertions, 283 deletions
diff --git a/tools/astro-languageserver/src/plugins/css/CSSDocument.ts b/tools/astro-languageserver/src/plugins/css/CSSDocument.ts index 90b28352c..9f1839678 100644 --- a/tools/astro-languageserver/src/plugins/css/CSSDocument.ts +++ b/tools/astro-languageserver/src/plugins/css/CSSDocument.ts @@ -4,92 +4,92 @@ import { getLanguageService } from './service'; import { Document, DocumentMapper, ReadableDocument, TagInformation } from '../../core/documents/index'; export interface CSSDocumentBase extends DocumentMapper, TextDocument { - languageId: string; - stylesheet: Stylesheet; + languageId: string; + stylesheet: Stylesheet; } export class CSSDocument extends ReadableDocument implements DocumentMapper { - private styleInfo: Pick<TagInformation, 'attributes' | 'start' | 'end'>; - readonly version = this.parent.version; + private styleInfo: Pick<TagInformation, 'attributes' | 'start' | 'end'>; + readonly version = this.parent.version; - public stylesheet: Stylesheet; - public languageId: string; + public stylesheet: Stylesheet; + public languageId: string; - constructor(private parent: Document) { - super(); + constructor(private parent: Document) { + super(); - if (this.parent.styleInfo) { - this.styleInfo = this.parent.styleInfo; - } else { - this.styleInfo = { - attributes: {}, - start: -1, - end: -1 - }; - } - - this.languageId = this.language; - this.stylesheet = getLanguageService(this.language).parseStylesheet(this); + if (this.parent.styleInfo) { + this.styleInfo = this.parent.styleInfo; + } else { + this.styleInfo = { + attributes: {}, + start: -1, + end: -1, + }; } - /** - * Get the fragment position relative to the parent - * @param pos Position in fragment - */ - getOriginalPosition(pos: Position): Position { - const parentOffset = this.styleInfo.start + this.offsetAt(pos); - return this.parent.positionAt(parentOffset); - } + this.languageId = this.language; + this.stylesheet = getLanguageService(this.language).parseStylesheet(this); + } - /** - * Get the position relative to the start of the fragment - * @param pos Position in parent - */ - getGeneratedPosition(pos: Position): Position { - const fragmentOffset = this.parent.offsetAt(pos) - this.styleInfo.start; - return this.positionAt(fragmentOffset); - } + /** + * Get the fragment position relative to the parent + * @param pos Position in fragment + */ + getOriginalPosition(pos: Position): Position { + const parentOffset = this.styleInfo.start + this.offsetAt(pos); + return this.parent.positionAt(parentOffset); + } - /** - * Returns true if the given parent position is inside of this fragment - * @param pos Position in parent - */ - isInGenerated(pos: Position): boolean { - const offset = this.parent.offsetAt(pos); - return offset >= this.styleInfo.start && offset <= this.styleInfo.end; - } + /** + * Get the position relative to the start of the fragment + * @param pos Position in parent + */ + getGeneratedPosition(pos: Position): Position { + const fragmentOffset = this.parent.offsetAt(pos) - this.styleInfo.start; + return this.positionAt(fragmentOffset); + } - /** - * Get the fragment text from the parent - */ - getText(): string { - return this.parent.getText().slice(this.styleInfo.start, this.styleInfo.end); - } + /** + * Returns true if the given parent position is inside of this fragment + * @param pos Position in parent + */ + isInGenerated(pos: Position): boolean { + const offset = this.parent.offsetAt(pos); + return offset >= this.styleInfo.start && offset <= this.styleInfo.end; + } - /** - * Returns the length of the fragment as calculated from the start and end positon - */ - getTextLength(): number { - return this.styleInfo.end - this.styleInfo.start; - } + /** + * Get the fragment text from the parent + */ + getText(): string { + return this.parent.getText().slice(this.styleInfo.start, this.styleInfo.end); + } - /** - * Return the parent file path - */ - getFilePath(): string | null { - return this.parent.getFilePath(); - } + /** + * Returns the length of the fragment as calculated from the start and end positon + */ + getTextLength(): number { + return this.styleInfo.end - this.styleInfo.start; + } - getURL() { - return this.parent.getURL(); - } + /** + * Return the parent file path + */ + getFilePath(): string | null { + return this.parent.getFilePath(); + } - getAttributes() { - return this.styleInfo.attributes; - } + getURL() { + return this.parent.getURL(); + } - private get language() { - const attrs = this.getAttributes(); - return attrs.lang || attrs.type || 'css'; - } + getAttributes() { + return this.styleInfo.attributes; + } + + private get language() { + const attrs = this.getAttributes(); + return attrs.lang || attrs.type || 'css'; + } } diff --git a/tools/astro-languageserver/src/plugins/css/CSSPlugin.ts b/tools/astro-languageserver/src/plugins/css/CSSPlugin.ts index 4c0dcb949..26c90ac66 100644 --- a/tools/astro-languageserver/src/plugins/css/CSSPlugin.ts +++ b/tools/astro-languageserver/src/plugins/css/CSSPlugin.ts @@ -26,24 +26,16 @@ export class CSSPlugin implements CompletionsProvider { }); } - getCompletions( - document: Document, - position: Position, - completionContext?: CompletionContext - ): CompletionList | null { + getCompletions(document: Document, position: Position, completionContext?: CompletionContext): CompletionList | null { const triggerCharacter = completionContext?.triggerCharacter; const triggerKind = completionContext?.triggerKind; const isCustomTriggerCharacter = triggerKind === CompletionTriggerKind.TriggerCharacter; - if ( - isCustomTriggerCharacter && - triggerCharacter && - !this.triggerCharacters.has(triggerCharacter) - ) { - return null; + if (isCustomTriggerCharacter && triggerCharacter && !this.triggerCharacters.has(triggerCharacter)) { + return null; } - if(this.isInsideFrontmatter(document, position)) { + if (this.isInsideFrontmatter(document, position)) { return null; } @@ -55,82 +47,55 @@ export class CSSPlugin implements CompletionsProvider { const attributeContext = getAttributeContextAtPosition(document, position); if (!attributeContext) { - return null; + return null; } if (this.inStyleAttributeWithoutInterpolation(attributeContext, document.getText())) { - const [start, end] = attributeContext.valueRange; - return this.getCompletionsInternal( - document, - position, - new StyleAttributeDocument(document, start, end) - ); + const [start, end] = attributeContext.valueRange; + return this.getCompletionsInternal(document, position, new StyleAttributeDocument(document, start, end)); } else { - return getIdClassCompletion(cssDocument, attributeContext); + return getIdClassCompletion(cssDocument, attributeContext); } } - private getCompletionsInternal( - document: Document, - position: Position, - cssDocument: CSSDocumentBase - ) { - if (isSASS(cssDocument)) { - // the css language service does not support sass, still we can use - // the emmet helper directly to at least get emmet completions - return doEmmetComplete(document, position, 'sass', this.configManager.getEmmetConfig()); - } - - const type = extractLanguage(cssDocument); - - const lang = getLanguageService(type); - const emmetResults: CompletionList = { - isIncomplete: true, - items: [] - }; - if (false /* this.configManager.getConfig().css.completions.emmet */) { - lang.setCompletionParticipants([ - getEmmetCompletionParticipants( - cssDocument, - cssDocument.getGeneratedPosition(position), - getLanguage(type), - this.configManager.getEmmetConfig(), - emmetResults - ) - ]); - } - const results = lang.doComplete( - cssDocument, - cssDocument.getGeneratedPosition(position), - cssDocument.stylesheet - ); - return CompletionList.create( - [...(results ? results.items : []), ...emmetResults.items].map((completionItem) => - mapCompletionItemToOriginal(cssDocument, completionItem) - ), - // Emmet completions change on every keystroke, so they are never complete - emmetResults.items.length > 0 - ); - } + private getCompletionsInternal(document: Document, position: Position, cssDocument: CSSDocumentBase) { + if (isSASS(cssDocument)) { + // the css language service does not support sass, still we can use + // the emmet helper directly to at least get emmet completions + return doEmmetComplete(document, position, 'sass', this.configManager.getEmmetConfig()); + } - private inStyleAttributeWithoutInterpolation( - attrContext: AttributeContext, - text: string - ): attrContext is Required<AttributeContext> { - return ( - attrContext.name === 'style' && - !!attrContext.valueRange && - !text.substring(attrContext.valueRange[0], attrContext.valueRange[1]).includes('{') + const type = extractLanguage(cssDocument); + + const lang = getLanguageService(type); + const emmetResults: CompletionList = { + isIncomplete: true, + items: [], + }; + if (false /* this.configManager.getConfig().css.completions.emmet */) { + lang.setCompletionParticipants([ + getEmmetCompletionParticipants(cssDocument, cssDocument.getGeneratedPosition(position), getLanguage(type), this.configManager.getEmmetConfig(), emmetResults), + ]); + } + const results = lang.doComplete(cssDocument, cssDocument.getGeneratedPosition(position), cssDocument.stylesheet); + return CompletionList.create( + [...(results ? results.items : []), ...emmetResults.items].map((completionItem) => mapCompletionItemToOriginal(cssDocument, completionItem)), + // Emmet completions change on every keystroke, so they are never complete + emmetResults.items.length > 0 ); } + private inStyleAttributeWithoutInterpolation(attrContext: AttributeContext, text: string): attrContext is Required<AttributeContext> { + return attrContext.name === 'style' && !!attrContext.valueRange && !text.substring(attrContext.valueRange[0], attrContext.valueRange[1]).includes('{'); + } + private getCSSDoc(document: Document) { - let cssDoc = this.documents.get(document); - if (!cssDoc || cssDoc.version < document.version) { - cssDoc = new CSSDocument(document); - this.documents.set(document, cssDoc); - } - return cssDoc; + let cssDoc = this.documents.get(document); + if (!cssDoc || cssDoc.version < document.version) { + cssDoc = new CSSDocument(document); + this.documents.set(document, cssDoc); + } + return cssDoc; } private isInsideFrontmatter(document: Document, position: Position) { @@ -140,14 +105,14 @@ export class CSSPlugin implements CompletionsProvider { function isSASS(document: CSSDocumentBase) { switch (extractLanguage(document)) { - case 'sass': - return true; - default: - return false; + case 'sass': + return true; + default: + return false; } } function extractLanguage(document: CSSDocumentBase): string { const lang = document.languageId; return lang.replace(/^text\//, ''); -}
\ No newline at end of file +} diff --git a/tools/astro-languageserver/src/plugins/css/StyleAttributeDocument.ts b/tools/astro-languageserver/src/plugins/css/StyleAttributeDocument.ts index 7b49d771d..e00398037 100644 --- a/tools/astro-languageserver/src/plugins/css/StyleAttributeDocument.ts +++ b/tools/astro-languageserver/src/plugins/css/StyleAttributeDocument.ts @@ -7,70 +7,66 @@ const PREFIX = '__ {'; const SUFFIX = '}'; export class StyleAttributeDocument extends ReadableDocument implements DocumentMapper { - readonly version = this.parent.version; + readonly version = this.parent.version; - public stylesheet: Stylesheet; - public languageId = 'css'; + public stylesheet: Stylesheet; + public languageId = 'css'; - constructor( - private readonly parent: Document, - private readonly attrStart: number, - private readonly attrEnd: number - ) { - super(); + constructor(private readonly parent: Document, private readonly attrStart: number, private readonly attrEnd: number) { + super(); - this.stylesheet = getLanguageService(this.languageId).parseStylesheet(this); - } + this.stylesheet = getLanguageService(this.languageId).parseStylesheet(this); + } - /** - * Get the fragment position relative to the parent - * @param pos Position in fragment - */ - getOriginalPosition(pos: Position): Position { - const parentOffset = this.attrStart + this.offsetAt(pos) - PREFIX.length; - return this.parent.positionAt(parentOffset); - } + /** + * Get the fragment position relative to the parent + * @param pos Position in fragment + */ + getOriginalPosition(pos: Position): Position { + const parentOffset = this.attrStart + this.offsetAt(pos) - PREFIX.length; + return this.parent.positionAt(parentOffset); + } - /** - * Get the position relative to the start of the fragment - * @param pos Position in parent - */ - getGeneratedPosition(pos: Position): Position { - const fragmentOffset = this.parent.offsetAt(pos) - this.attrStart + PREFIX.length; - return this.positionAt(fragmentOffset); - } + /** + * Get the position relative to the start of the fragment + * @param pos Position in parent + */ + getGeneratedPosition(pos: Position): Position { + const fragmentOffset = this.parent.offsetAt(pos) - this.attrStart + PREFIX.length; + return this.positionAt(fragmentOffset); + } - /** - * Returns true if the given parent position is inside of this fragment - * @param pos Position in parent - */ - isInGenerated(pos: Position): boolean { - const offset = this.parent.offsetAt(pos); - return offset >= this.attrStart && offset <= this.attrEnd; - } + /** + * Returns true if the given parent position is inside of this fragment + * @param pos Position in parent + */ + isInGenerated(pos: Position): boolean { + const offset = this.parent.offsetAt(pos); + return offset >= this.attrStart && offset <= this.attrEnd; + } - /** - * Get the fragment text from the parent - */ - getText(): string { - return PREFIX + this.parent.getText().slice(this.attrStart, this.attrEnd) + SUFFIX; - } + /** + * Get the fragment text from the parent + */ + getText(): string { + return PREFIX + this.parent.getText().slice(this.attrStart, this.attrEnd) + SUFFIX; + } - /** - * Returns the length of the fragment as calculated from the start and end position - */ - getTextLength(): number { - return PREFIX.length + this.attrEnd - this.attrStart + SUFFIX.length; - } + /** + * Returns the length of the fragment as calculated from the start and end position + */ + getTextLength(): number { + return PREFIX.length + this.attrEnd - this.attrStart + SUFFIX.length; + } - /** - * Return the parent file path - */ - getFilePath(): string | null { - return this.parent.getFilePath(); - } + /** + * Return the parent file path + */ + getFilePath(): string | null { + return this.parent.getFilePath(); + } - getURL() { - return this.parent.getURL(); - } -}
\ No newline at end of file + getURL() { + return this.parent.getURL(); + } +} diff --git a/tools/astro-languageserver/src/plugins/css/features/getIdClassCompletion.ts b/tools/astro-languageserver/src/plugins/css/features/getIdClassCompletion.ts index 368359ac9..45acb5ad6 100644 --- a/tools/astro-languageserver/src/plugins/css/features/getIdClassCompletion.ts +++ b/tools/astro-languageserver/src/plugins/css/features/getIdClassCompletion.ts @@ -2,32 +2,29 @@ import { CompletionItem, CompletionItemKind, CompletionList } from 'vscode-langu import { AttributeContext } from '../../../core/documents/parseHtml'; import { CSSDocument } from '../CSSDocument'; -export function getIdClassCompletion( - cssDoc: CSSDocument, - attributeContext: AttributeContext -): CompletionList | null { - const collectingType = getCollectingType(attributeContext); +export function getIdClassCompletion(cssDoc: CSSDocument, attributeContext: AttributeContext): CompletionList | null { + const collectingType = getCollectingType(attributeContext); - if (!collectingType) { - return null; - } - const items = collectSelectors(cssDoc.stylesheet as CSSNode, collectingType); + if (!collectingType) { + return null; + } + const items = collectSelectors(cssDoc.stylesheet as CSSNode, collectingType); - console.log("getIdClassCompletion items", items.length); - return CompletionList.create(items); + console.log('getIdClassCompletion items', items.length); + return CompletionList.create(items); } function getCollectingType(attributeContext: AttributeContext): number | undefined { - if (attributeContext.inValue) { - if (attributeContext.name === 'class') { - return NodeType.ClassSelector; - } - if (attributeContext.name === 'id') { - return NodeType.IdentifierSelector; - } - } else if (attributeContext.name.startsWith('class:')) { - return NodeType.ClassSelector; + if (attributeContext.inValue) { + if (attributeContext.name === 'class') { + return NodeType.ClassSelector; + } + if (attributeContext.name === 'id') { + return NodeType.IdentifierSelector; } + } else if (attributeContext.name.startsWith('class:')) { + return NodeType.ClassSelector; + } } /** @@ -36,35 +33,35 @@ function getCollectingType(attributeContext: AttributeContext): number | undefin * The enum is not exported. we have to update this whenever it changes */ export enum NodeType { - ClassSelector = 14, - IdentifierSelector = 15 + ClassSelector = 14, + IdentifierSelector = 15, } export type CSSNode = { - type: number; - children: CSSNode[] | undefined; - getText(): string; + type: number; + children: CSSNode[] | undefined; + getText(): string; }; export function collectSelectors(stylesheet: CSSNode, type: number) { - const result: CSSNode[] = []; - walk(stylesheet, (node) => { - if (node.type === type) { - result.push(node); - } - }); + const result: CSSNode[] = []; + walk(stylesheet, (node) => { + if (node.type === type) { + result.push(node); + } + }); - return result.map( - (node): CompletionItem => ({ - label: node.getText().substring(1), - kind: CompletionItemKind.Keyword - }) - ); + return result.map( + (node): CompletionItem => ({ + label: node.getText().substring(1), + kind: CompletionItemKind.Keyword, + }) + ); } function walk(node: CSSNode, callback: (node: CSSNode) => void) { - callback(node); - if (node.children) { - node.children.forEach((node) => walk(node, callback)); - } -}
\ No newline at end of file + callback(node); + if (node.children) { + node.children.forEach((node) => walk(node, callback)); + } +} diff --git a/tools/astro-languageserver/src/plugins/css/service.ts b/tools/astro-languageserver/src/plugins/css/service.ts index e8ac86a65..78b11296e 100644 --- a/tools/astro-languageserver/src/plugins/css/service.ts +++ b/tools/astro-languageserver/src/plugins/css/service.ts @@ -1,58 +1,48 @@ -import { - getCSSLanguageService, - getSCSSLanguageService, - getLESSLanguageService, - LanguageService, - ICSSDataProvider -} from 'vscode-css-languageservice'; +import { getCSSLanguageService, getSCSSLanguageService, getLESSLanguageService, LanguageService, ICSSDataProvider } from 'vscode-css-languageservice'; const customDataProvider: ICSSDataProvider = { providePseudoClasses() { - return []; + return []; }, provideProperties() { - return []; + return []; }, provideAtDirectives() { - return []; + return []; }, providePseudoElements() { - return []; - } + return []; + }, }; -const [css, scss, less] = [ - getCSSLanguageService, - getSCSSLanguageService, - getLESSLanguageService -].map((getService) => +const [css, scss, less] = [getCSSLanguageService, getSCSSLanguageService, getLESSLanguageService].map((getService) => getService({ - customDataProviders: [customDataProvider] + customDataProviders: [customDataProvider], }) ); const langs = { css, scss, - less + less, }; export function getLanguage(kind?: string) { switch (kind) { - case 'scss': - case 'text/scss': - return 'scss' as const; - case 'less': - case 'text/less': - return 'less' as const; - case 'css': - case 'text/css': - default: - return 'css' as const; + case 'scss': + case 'text/scss': + return 'scss' as const; + case 'less': + case 'text/less': + return 'less' as const; + case 'css': + case 'text/css': + default: + return 'css' as const; } } export function getLanguageService(kind?: string): LanguageService { const lang = getLanguage(kind); return langs[lang]; -}
\ No newline at end of file +} diff --git a/tools/astro-languageserver/src/plugins/index.ts b/tools/astro-languageserver/src/plugins/index.ts index 368b339cb..bb73cbe5e 100644 --- a/tools/astro-languageserver/src/plugins/index.ts +++ b/tools/astro-languageserver/src/plugins/index.ts @@ -3,4 +3,4 @@ export * from './astro/AstroPlugin'; export * from './html/HTMLPlugin'; export * from './typescript/TypeScriptPlugin'; export * from './interfaces'; -export * from './css/CSSPlugin';
\ No newline at end of file +export * from './css/CSSPlugin'; |