Skip to content

Commit

Permalink
@import and url() links. Fix microsoft/vscode#29899.
Browse files Browse the repository at this point in the history
  • Loading branch information
octref committed Aug 14, 2018
1 parent 6f20207 commit 9f993e1
Show file tree
Hide file tree
Showing 3 changed files with 231 additions and 104 deletions.
4 changes: 3 additions & 1 deletion src/cssLanguageService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

import {
TextDocument, Position, CompletionList, Hover, Range, SymbolInformation, Diagnostic, Location, DocumentHighlight,
CodeActionContext, Command, WorkspaceEdit, Color, ColorInformation, ColorPresentation, FoldingRange
CodeActionContext, Command, WorkspaceEdit, Color, ColorInformation, ColorPresentation, FoldingRange, DocumentLink
} from 'vscode-languageserver-types';

import { Parser } from './parser/cssParser';
Expand Down Expand Up @@ -37,6 +37,7 @@ export interface LanguageService {
findDefinition(document: TextDocument, position: Position, stylesheet: Stylesheet): Location | null;
findReferences(document: TextDocument, position: Position, stylesheet: Stylesheet): Location[];
findDocumentHighlights(document: TextDocument, position: Position, stylesheet: Stylesheet): DocumentHighlight[];
findDocumentLinks(document: TextDocument, stylesheet: Stylesheet): DocumentLink[];
findDocumentSymbols(document: TextDocument, stylesheet: Stylesheet): SymbolInformation[];
doCodeActions(document: TextDocument, range: Range, context: CodeActionContext, stylesheet: Stylesheet): Command[];
/** deprecated, use findDocumentColors instead */
Expand All @@ -58,6 +59,7 @@ function createFacade(parser: Parser, completion: CSSCompletion, hover: CSSHover
findDefinition: navigation.findDefinition.bind(navigation),
findReferences: navigation.findReferences.bind(navigation),
findDocumentHighlights: navigation.findDocumentHighlights.bind(navigation),
findDocumentLinks: navigation.findDocumentLinks.bind(navigation),
findDocumentSymbols: navigation.findDocumentSymbols.bind(navigation),
doCodeActions: codeActions.doCodeActions.bind(codeActions),
findColorSymbols: (d, s) => navigation.findDocumentColors(d, s).map(s => s.range),
Expand Down
66 changes: 65 additions & 1 deletion src/services/cssNavigation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,16 @@
'use strict';

import * as nodes from '../parser/cssNodes';
import { resolve as resolveUrl } from 'url';
import {
TextDocument, Range, Position, Location, DocumentHighlightKind, DocumentHighlight,
SymbolInformation, SymbolKind, WorkspaceEdit, TextEdit, ColorInformation, ColorPresentation, Color
SymbolInformation, SymbolKind, WorkspaceEdit, TextEdit, ColorInformation, ColorPresentation, Color, DocumentLink
} from 'vscode-languageserver-types';
import { Symbols } from '../parser/cssSymbolScope';
import { getColorValue, hslFromColor } from '../services/languageFacts';

import * as nls from 'vscode-nls';
import { startsWith } from '../utils/strings';

const localize = nls.loadMessageBundle();

Expand Down Expand Up @@ -84,6 +86,37 @@ export class CSSNavigation {
return result;
}

public findDocumentLinks(document: TextDocument, stylesheet: nodes.Stylesheet): DocumentLink[] {
const result: DocumentLink[] = [];

stylesheet.accept(candidate => {
if (candidate.type === nodes.NodeType.URILiteral) {
const link = uriLiteralNodeToDocumentLink(document, candidate);
if (link) {
result.push(link);
}
return false;
}

/**
* In @import, it is possible to include links that do not use `url()`
* For example, `@import 'foo.css';`
*/
if (candidate.parent && candidate.parent.type === nodes.NodeType.Import) {
const rawText = candidate.getText();
if (startsWith(rawText, `'`) || startsWith(rawText, `"`)) {
result.push(uriStringNodeToDocumentLink(document, candidate));
}

return false;
}

return true;
});

return result;
}

public findDocumentSymbols(document: TextDocument, stylesheet: nodes.Stylesheet): SymbolInformation[] {

let result: SymbolInformation[] = [];
Expand Down Expand Up @@ -186,6 +219,37 @@ function getColorInformation(node: nodes.Node, document: TextDocument): ColorInf
return null;
}

function uriLiteralNodeToDocumentLink(document: TextDocument, uriLiteralNode: nodes.Node): DocumentLink {
if (uriLiteralNode.getChildren().length === 0) {
return null;
}

const uriStringNode = uriLiteralNode.getChild(0);

return uriStringNodeToDocumentLink(document, uriStringNode);
}

function uriStringNodeToDocumentLink(document: TextDocument, uriStringNode: nodes.Node) {
let rawUri = uriStringNode.getText();
const range = getRange(uriStringNode, document);
if (startsWith(rawUri, `'`) || startsWith(rawUri, `"`)) {
rawUri = rawUri.slice(1, -1);
}
let target: string;
if (startsWith(rawUri, 'http') || startsWith(rawUri, 'https')) {
target = rawUri;
} else if (/^\w+:\/\//g.test(rawUri)) {
target = rawUri;
}
else {
target = resolveUrl(document.uri, rawUri);
}
return {
range,
target
};
}

function getRange(node: nodes.Node, document: TextDocument): Range {
return Range.create(document.positionAt(node.offset), document.positionAt(node.end));
}
Expand Down
Loading

0 comments on commit 9f993e1

Please sign in to comment.