New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

cssmodules-language-server

Package Overview
Dependencies
Maintainers
1
Versions
12
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

cssmodules-language-server - npm Package Compare versions

Comparing version

to
1.1.0

LICENSE

4

lib/connection.js

@@ -46,3 +46,5 @@ "use strict";

textDocumentSync: lsp.TextDocumentSyncKind.Incremental,
hoverProvider: true,
definitionProvider: true,
implementationProvider: true,
completionProvider: {

@@ -68,4 +70,6 @@ /**

connection.onDefinition(definitionProvider.definition);
connection.onImplementation(definitionProvider.definition);
connection.onHover(definitionProvider.hover);
return connection;
}
exports.createConnection = createConnection;

4

lib/DefinitionProvider.d.ts

@@ -1,2 +0,2 @@

import { Location, Position } from 'vscode-languageserver-protocol';
import { Hover, Location, Position } from 'vscode-languageserver-protocol';
import { TextDocument } from 'vscode-languageserver-textdocument';

@@ -10,3 +10,5 @@ import * as lsp from 'vscode-languageserver/node';

definition: (params: lsp.DefinitionParams) => Promise<never[] | Location | null>;
hover: (params: lsp.HoverParams) => Promise<Hover | null>;
provideHover(textdocument: TextDocument, position: Position): Promise<null | Hover>;
provideDefinition(textdocument: TextDocument, position: Position): Promise<Location | null>;
}

@@ -30,2 +30,9 @@ "use strict";

});
this.hover = (params) => __awaiter(this, void 0, void 0, function* () {
const textdocument = textDocuments_1.textDocuments.get(params.textDocument.uri);
if (textdocument === undefined) {
return null;
}
return this.provideHover(textdocument, params.position);
});
this._camelCaseConfig = camelCaseConfig;

@@ -36,2 +43,32 @@ }

}
provideHover(textdocument, position) {
return __awaiter(this, void 0, void 0, function* () {
const fileContent = textdocument.getText();
const lines = fileContent.split(os_1.EOL);
const currentLine = lines[position.line];
if (typeof currentLine !== 'string') {
return null;
}
const currentDir = (0, utils_1.getCurrentDirFromUri)(textdocument.uri);
const words = (0, utils_1.getWords)(currentLine, position);
if (words === '' || words.indexOf('.') === -1) {
return null;
}
const [obj, field] = words.split('.');
const importPath = (0, utils_1.findImportPath)(fileContent, obj, currentDir);
if (importPath === '') {
return null;
}
const dict = yield (0, utils_1.filePathToClassnameDict)(importPath, (0, utils_1.getTransformer)(this._camelCaseConfig));
const node = dict[`.${field}`];
if (!node)
return null;
return {
contents: {
language: 'css',
value: (0, utils_1.stringiyClassname)(field, node.declarations, node.comments),
},
};
});
}
provideDefinition(textdocument, position) {

@@ -38,0 +75,0 @@ return __awaiter(this, void 0, void 0, function* () {

@@ -15,6 +15,12 @@ import { Position } from 'vscode-languageserver-protocol';

export declare function getWords(line: string, position: Position): string;
declare type Classname = {
declare type ClassnamePostion = {
line: number;
column: number;
};
export declare type Classname = {
position: ClassnamePostion;
declarations: string[];
comments: string[];
};
declare type ClassnameDict = Record<string, Classname>;
export declare const log: (...args: unknown[]) => void;

@@ -26,11 +32,17 @@ /**

*
* ```
* ```js
* {
* '.foo': {
* line: 10,
* column: 5,
* declarations: [],
* position: {
* line: 10,
* column: 5,
* },
* },
* '.bar': {
* line: 22,
* column: 1,
* declarations: ['width: 52px'],
* position: {
* line: 22,
* column: 1,
* }
* }

@@ -40,3 +52,3 @@ * }

*/
export declare function filePathToClassnameDict(filepath: string, classnameTransformer: StringTransformer): Promise<Record<string, Classname>>;
export declare function filePathToClassnameDict(filepath: string, classnameTransformer: StringTransformer): Promise<ClassnameDict>;
/**

@@ -46,2 +58,3 @@ * Get all classnames from the file contents

export declare function getAllClassNames(filePath: string, keyword: string, classnameTransformer: StringTransformer): Promise<string[]>;
export declare function stringiyClassname(classname: string, declarations: string[], comments: string[]): string;
export {};

@@ -15,3 +15,3 @@ "use strict";

Object.defineProperty(exports, "__esModule", { value: true });
exports.getAllClassNames = exports.filePathToClassnameDict = exports.log = exports.getWords = exports.getPosition = exports.isImportLineMatch = exports.getTransformer = exports.findImportPath = exports.genImportRegExp = exports.getCurrentDirFromUri = void 0;
exports.stringiyClassname = exports.getAllClassNames = exports.filePathToClassnameDict = exports.log = exports.getWords = exports.getPosition = exports.isImportLineMatch = exports.getTransformer = exports.findImportPath = exports.genImportRegExp = exports.getCurrentDirFromUri = void 0;
const vscode_languageserver_protocol_1 = require("vscode-languageserver-protocol");

@@ -84,3 +84,5 @@ const path_1 = __importDefault(require("path"));

const target = classDict[`.${className}`];
return target ? vscode_languageserver_protocol_1.Position.create(target.line - 1, target.column) : null;
return target
? vscode_languageserver_protocol_1.Position.create(target.position.line - 1, target.position.column)
: null;
});

@@ -149,11 +151,17 @@ }

*
* ```
* ```js
* {
* '.foo': {
* line: 10,
* column: 5,
* declarations: [],
* position: {
* line: 10,
* column: 5,
* },
* },
* '.bar': {
* line: 22,
* column: 1,
* declarations: ['width: 52px'],
* position: {
* line: 22,
* column: 1,
* }
* }

@@ -187,10 +195,20 @@ * }

const stack = [...ast.root.nodes];
let commentStack = [];
while (stack.length) {
const node = stack.shift();
if ((node === null || node === void 0 ? void 0 : node.type) === 'atrule' && node.name.toLowerCase() === 'media') {
stack.unshift(...node.nodes);
if (node === undefined)
continue;
if (node.type === 'comment') {
commentStack.push(node);
continue;
}
if ((node === null || node === void 0 ? void 0 : node.type) !== 'rule')
if (node.type === 'atrule') {
if (node.name.toLowerCase() === 'media') {
stack.unshift(...node.nodes);
}
commentStack = [];
continue;
}
if (node.type !== 'rule')
continue;
const selectors = node.selector.split(',').map(sanitizeSelector);

@@ -214,5 +232,15 @@ selectors.forEach(sels => {

dict[classnameTransformer(name)] = {
column: column + lastLine.length,
line: line + lines.length - 1,
declarations: node.nodes.reduce((acc, x) => {
if (x.type === 'decl') {
acc.push(`${x.prop}: ${x.value};`);
}
return acc;
}, []),
position: {
column: column + lastLine.length,
line: line + lines.length - 1,
},
comments: commentStack.map(x => x.text),
};
commentStack = [];
});

@@ -240,5 +268,15 @@ visitedNodes.set(node, { selectors });

dict[classnameTransformer(classname)] = {
column: column,
line: line,
declarations: node.nodes.reduce((acc, x) => {
if (x.type === 'decl') {
acc.push(`${x.prop}: ${x.value};`);
}
return acc;
}, []),
position: {
column: column,
line: line,
},
comments: commentStack.map(x => x.text),
};
commentStack = [];
}));

@@ -267,1 +305,27 @@ visitedNodes.set(node, { selectors: finishedSelectors });

exports.getAllClassNames = getAllClassNames;
function stringiyClassname(classname, declarations, comments) {
const commentString = comments.length
? comments
.map(x => {
const lines = x.split(os_1.EOL);
if (lines.length < 2) {
return `/*${x} */`;
}
else {
return [
`/*${lines[0]}`,
...lines.slice(1).map(y => ` ${y.trimStart()}`),
' */',
].join(os_1.EOL);
}
})
.join(os_1.EOL) + os_1.EOL
: '';
return (commentString +
[
`.${classname} {${declarations.length ? '' : '}'}`,
...declarations.map(x => ` ${x}`),
...(declarations.length ? ['}'] : []),
].join(os_1.EOL));
}
exports.stringiyClassname = stringiyClassname;
{
"name": "cssmodules-language-server",
"version": "1.0.1",
"version": "1.1.0",
"description": "language server for cssmodules",

@@ -5,0 +5,0 @@ "bin": {

@@ -7,2 +7,8 @@ # cssmodules-language-server

Features:
- **definition** jumps to class name under cursor.
- **implementation** (works the same as definition).
- **hover** provides comments before the class name with direct declarations within the class name.
The supported languages are `css`(postcss), `sass` and `scss`. `styl` files are parsed as regular `css`.

@@ -22,29 +28,25 @@

Example uses [`nvim-lspconfig`](https://github.com/neovim/lspconfig)
Example uses [`nvim-lspconfig`](https://github.com/neovim/nvim-lspconfig)
```lua
local configs = require'lspconfig/configs'
require'lspconfig'.cssmodules_ls.setup {
-- provide your on_attach to bind keymappings
on_attach = custom_on_attach,
-- optionally
init_options = {
camelCase = 'dashes',
},
}
```
if not configs.cssmodules then
configs.cssmodules = {
default_config = {
cmd = {'cssmodules-language-server'},
filetypes = {'javascript', 'javascriptreact', 'typescript', 'typescriptreact'},
init_options = {
camelCase = 'dashes',
},
root_dir = require('lspconfig.util').root_pattern('package.json')
},
docs = {
description = 'TODO description',
default_config = {
root_dir = '[[root_pattern("package.json")]]'
}
}
}
end
**Known issue**: if you have multiple LSP that provide hover and go-to-definition support, there can be races(example typescript and cssmodules-language-server work simultaneously). As a workaround you can disable **definition** in favor of **implementation** to avoid conflicting with typescript's go-to-definition.
configs.cssmodules.setup {}
-- or
-- configs.cssmodules.setup {on_attach = custom_on_attach}
```lua
require'lspconfig'.cssmodules_ls.setup {
on_attach = function (client)
-- avoid accepting `go-to-definition` responses from this LSP
client.resolved_capabilities.goto_definition = false
custom_on_attach(client)
end,
}
```

@@ -51,0 +53,0 @@