css.experimental.customData

This commit is contained in:
Pine Wu 2019-01-07 16:52:04 -08:00
parent 439e20c7b6
commit f7894236ee
5 changed files with 80 additions and 7 deletions

View file

@ -0,0 +1,2 @@
{
}

View file

@ -9,7 +9,7 @@ import * as fs from 'fs';
import * as nls from 'vscode-nls';
const localize = nls.loadMessageBundle();
import { languages, window, commands, ExtensionContext, Range, Position, CompletionItem, CompletionItemKind, TextEdit, SnippetString } from 'vscode';
import { languages, window, commands, ExtensionContext, Range, Position, CompletionItem, CompletionItemKind, TextEdit, SnippetString, workspace } from 'vscode';
import { LanguageClient, LanguageClientOptions, ServerOptions, TransportKind, Disposable } from 'vscode-languageclient';
// this method is called when vs code is activated
@ -30,6 +30,22 @@ export function activate(context: ExtensionContext) {
let documentSelector = ['css', 'scss', 'less'];
let dataPaths: string[] = workspace.getConfiguration('css').get('experimental.customData', []);
if (dataPaths && dataPaths.length > 0) {
if (!workspace.workspaceFolders) {
dataPaths = [];
} else {
try {
const workspaceRoot = workspace.workspaceFolders[0].uri.fsPath;
dataPaths = dataPaths.map(d => {
return path.resolve(workspaceRoot, d);
});
} catch (err) {
dataPaths = [];
}
}
}
// Options to control the language client
let clientOptions: LanguageClientOptions = {
documentSelector,
@ -37,6 +53,7 @@ export function activate(context: ExtensionContext) {
configurationSection: ['css', 'scss', 'less']
},
initializationOptions: {
dataPaths
}
};

View file

@ -32,6 +32,10 @@
"id": "css",
"title": "%css.title%",
"properties": {
"css.experimental.customData": {
"type": "array",
"description": "A list of JSON file paths that define custom CSS data that loads extra properties, at directives, pseudo classes / elements."
},
"css.validate": {
"type": "boolean",
"scope": "resource",

View file

@ -7,6 +7,7 @@ import {
createConnection, IConnection, TextDocuments, InitializeParams, InitializeResult, ServerCapabilities, ConfigurationRequest, WorkspaceFolder
} from 'vscode-languageserver';
import URI from 'vscode-uri';
import * as fs from 'fs';
import { TextDocument, CompletionList } from 'vscode-languageserver-types';
import { getCSSLanguageService, getSCSSLanguageService, getLESSLanguageService, LanguageSettings, LanguageService, Stylesheet } from 'vscode-css-languageservice';
@ -14,6 +15,7 @@ import { getLanguageModelCache } from './languageModelCache';
import { getPathCompletionParticipant } from './pathCompletion';
import { formatError, runSafe } from './utils/runner';
import { getDocumentContext } from './utils/documentContext';
import { parseCSSData } from './languageFacts';
export interface Settings {
css: LanguageSettings;
@ -50,6 +52,8 @@ let scopedSettingsSupport = false;
let foldingRangeLimit = Number.MAX_VALUE;
let workspaceFolders: WorkspaceFolder[];
const languageServices: { [id: string]: LanguageService } = {};
// After the server has started the client sends an initialize request. The server receives
// in the passed params the rootPath of the workspace plus the client capabilities.
connection.onInitialize((params: InitializeParams): InitializeResult => {
@ -61,6 +65,33 @@ connection.onInitialize((params: InitializeParams): InitializeResult => {
}
}
const dataPaths: string[] = params.initializationOptions.dataPaths;
let customData = {
customProperties: [],
customAtDirectives: [],
customPseudoElements: [],
customPseudoClasses: []
};
dataPaths.forEach(p => {
if (fs.existsSync(p)) {
const {
properties,
atDirectives,
pseudoClasses,
pseudoElements
} = parseCSSData(fs.readFileSync(p, 'utf-8'));
customData.customProperties = customData.customProperties.concat(properties);
customData.customAtDirectives = customData.customAtDirectives.concat(atDirectives);
customData.customPseudoClasses = customData.customPseudoClasses.concat(pseudoClasses);
customData.customPseudoElements = customData.customPseudoElements.concat(pseudoElements);
} else {
return;
}
});
function getClientCapability<T>(name: string, def: T) {
const keys = name.split('.');
let c: any = params.capabilities;
@ -76,6 +107,10 @@ connection.onInitialize((params: InitializeParams): InitializeResult => {
scopedSettingsSupport = !!getClientCapability('workspace.configuration', false);
foldingRangeLimit = getClientCapability('textDocument.foldingRange.rangeLimit', Number.MAX_VALUE);
languageServices.css = getCSSLanguageService(customData);
languageServices.scss = getSCSSLanguageService(customData);
languageServices.less = getLESSLanguageService(customData);
const capabilities: ServerCapabilities = {
// Tell the client that the server works in FULL text document sync mode
textDocumentSync: documents.syncKind,
@ -96,12 +131,6 @@ connection.onInitialize((params: InitializeParams): InitializeResult => {
return { capabilities };
});
const languageServices: { [id: string]: LanguageService } = {
css: getCSSLanguageService(),
scss: getSCSSLanguageService(),
less: getLESSLanguageService()
};
function getLanguageService(document: TextDocument) {
let service = languageServices[document.languageId];
if (!service) {

View file

@ -0,0 +1,21 @@
/*---------------------------------------------------------------------------------------------
* Copyright (c) Microsoft Corporation. All rights reserved.
* Licensed under the MIT License. See License.txt in the project root for license information.
*--------------------------------------------------------------------------------------------*/
export function parseCSSData(source: string) {
let rawData: any;
try {
rawData = JSON.parse(source);
} catch (err) {
return {};
}
return {
properties: rawData.properties || [],
atDirectives: rawData.atdirectives || [],
pseudoClasses: rawData.pseudoclasses || [],
pseudoElements: rawData.pseudoelements || []
};
}