Skip to content

Commit

Permalink
feat: add support for unstable feature no_sort
Browse files Browse the repository at this point in the history
This feature add support for issue #10
  • Loading branch information
phoenisx committed Sep 11, 2021
1 parent e4d99e8 commit 18e4f0e
Show file tree
Hide file tree
Showing 10 changed files with 354 additions and 16 deletions.
9 changes: 6 additions & 3 deletions .eslintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,29 @@
"env": {
"browser": false,
"node": true,
"es6": true
"es6": true,
"jest/globals": true
},
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/recommended",
"prettier"
"prettier",
"plugin:jest/recommended"
],
"parser": "@typescript-eslint/parser",
"parserOptions": {
"ecmaVersion": 6,
"sourceType": "module"
},
"plugins": ["@typescript-eslint", "prettier"],
"plugins": ["@typescript-eslint", "prettier", "jest"],
"rules": {
"@typescript-eslint/camelcase": 0,
"@typescript-eslint/explicit-function-return-type": 0,
"@typescript-eslint/explicit-module-boundary-types": 0,
"@typescript-eslint/no-explicit-any": 0,
"@typescript-eslint/no-unused-vars": ["error", { "argsIgnorePattern": "^_" }],
"@typescript-eslint/no-var-requires": 0,
"@typescript-eslint/ban-ts-comment": 1,
"prettier/prettier": "error",
"no-console":"error"
}
Expand Down
File renamed without changes.
File renamed without changes.
54 changes: 54 additions & 0 deletions __mocks__/vscode.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
const CompletionItemKind = {
Color: 15,
Variable: 5,
};

class CompletionItem {
/**
* @type {(label: string, kind?: CompletionItemKind | undefined): CompletionItem}
*/
constructor(lable, kind) {
this.label = lable;
this.kind = kind;
}
}

class Position {
/**
* @param {number} line
* @param {number} char
*/
constructor(line, char) {
this.line = line;
this.character = char;
}

with = jest.fn().mockImplementation((start, end) => {
return new Range(start, end);
});
}

class Range {
/**
* @param {Position} start
* @param {Position} end
*/
constructor(start, end) {
this.start = start;
this.end = end;
}
}

const workspace = {
getConfiguration: jest.fn(),
workspaceFolders: [],
onDidSaveTextDocument: jest.fn(),
};

module.exports = {
CompletionItemKind,
CompletionItem,
workspace,
Position,
Range,
};
14 changes: 12 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
"preview": false,
"contributes": {
"configuration": {
"title": "CSS Var Complete - An Autocompletion Intellisense tool for CSS Variables",
"title": "CSS Var Complete",
"properties": {
"cssvar.files": {
"type": [
Expand Down Expand Up @@ -76,6 +76,15 @@
"type": "boolean",
"default": false,
"description": "Exclude themed variables"
},
"cssvar.unstable": {
"type": [
"array",
"null"
],
"default": null,
"pattern": "no_sort",
"description": "Enable various unstable feature for the extension"
}
}
}
Expand All @@ -89,7 +98,7 @@
"watch": "rollup -c -m -w",
"lint": "eslint src --ext ts",
"lint:fix": "eslint src --ext ts --fix",
"test": "cross-env NODE_ENV=production jest --rootDir src/test"
"test": "cross-env NODE_ENV=production jest"
},
"devDependencies": {
"@babel/core": "^7.13.15",
Expand All @@ -110,6 +119,7 @@
"esbuild": "^0.10.2",
"eslint": "^7.19.0",
"eslint-config-prettier": "^8.1.0",
"eslint-plugin-jest": "^24.4.0",
"eslint-plugin-prettier": "^3.3.1",
"husky": "^5.2.0",
"jest": "^26.6.3",
Expand Down
7 changes: 7 additions & 0 deletions src/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -29,18 +29,25 @@ export type SupportedExtensionNames =
| "javascript"
| "javascriptreact";

export const UNSTABLE_FEATURES = {
no_sort: false,
};
export type UnstableFeatures = (keyof typeof UNSTABLE_FEATURES)[];

export interface Config {
files: string[] | Record<string, string[]>;
extensions: SupportedExtensionNames[];
themes: string[];
excludeThemedVariables: boolean;
unstable: UnstableFeatures;
}

export const DEFAULT_CONFIG: Config = {
files: ["index.css"],
extensions: ["css", "scss", "sass", "less"],
themes: [],
excludeThemedVariables: false,
unstable: [],
};

export const mapShortToFullExtension = (
Expand Down
36 changes: 27 additions & 9 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,10 @@ import {
SUFFIX,
SupportedExtensionNames,
SupportedLanguageIds,
UNSTABLE_FEATURES,
} from "./constants";
import { getCSSDeclarationArray, isCSSInJS, isObjectProperty } from "./utils";
import { disableDefaultSort } from "./unstable";

/**
* Sets up the Plugin
Expand All @@ -39,19 +41,19 @@ export async function setup(): Promise<{ config: Config }> {
const config: Record<keyof Config, ValueOf<Config>> = {} as Config;
for (const key in DEFAULT_CONFIG) {
if (isObjectProperty(DEFAULT_CONFIG, key)) {
const value = _config.get<ValueOf<Config>>(key) || DEFAULT_CONFIG[key];
switch (key) {
case "files": {
const value =
_config.get<Config[typeof key]>(key) || DEFAULT_CONFIG[key];
if (isMultiRoot) {
const _value = <Record<string, string[]>>value;
config[key] = [];
for (const workspaceName of Object.keys(_value)) {
for (const workspaceName of Object.keys(value)) {
const wFolder = workspace.workspaceFolders.find(w => {
return new RegExp(workspaceName).test(w.name);
});
if (wFolder) {
const _resourcePath = wFolder.uri.fsPath;
const globs = _value[workspaceName];
const globs = (<Record<string, string[]>>value)[workspaceName];
const entries = await fastGlob(globs, {
cwd: _resourcePath,
});
Expand All @@ -70,17 +72,31 @@ export async function setup(): Promise<{ config: Config }> {
}
break;
}
case "extensions":
config[key] = (<SupportedExtensionNames[]>value).map(ext => {
case "extensions": {
const value =
_config.get<Config[typeof key]>(key) || DEFAULT_CONFIG[key];
config[key] = value.map(ext => {
const _ext = ext.startsWith(".")
? (ext.substr(1) as SupportedExtensionNames)
: ext;
return mapShortToFullExtension(_ext);
});
break;
default:
}
case "unstable": {
const value =
_config.get<Config[typeof key]>(key) || DEFAULT_CONFIG[key];
value.forEach(featureKey => {
UNSTABLE_FEATURES[featureKey] = true;
});
break;
}
default: {
const value =
_config.get<Config[typeof key]>(key) || DEFAULT_CONFIG[key];
config[key] = value;
break;
}
}
}
}
Expand All @@ -103,7 +119,7 @@ export interface Region {
suffixChar: string;
}

export const getRegion = (line: string, currentRange: Range) => {
export const getRegion = (line: string, currentRange: Range): Region | null => {
const match = line.match(FILTER_REGEX);
if (match) {
const filtered = match[1];
Expand Down Expand Up @@ -134,7 +150,8 @@ export const createCompletionItems = (
} = { languageId: "css" }
) => {
const vars = getCSSDeclarationArray(cssVars);
return vars.reduce<CompletionItem[]>((items, cssVar) => {
const size = vars.length;
return vars.reduce<CompletionItem[]>((items, cssVar, index) => {
const KIND = cssVar.color
? CompletionItemKind.Color
: CompletionItemKind.Variable;
Expand All @@ -158,6 +175,7 @@ export const createCompletionItems = (
}
item.insertText = insertText;
item.range = options.region.range;
disableDefaultSort(item, { size, index });
}
items.push(item);
return items;
Expand Down
143 changes: 143 additions & 0 deletions src/test/main.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,143 @@
import { Position, Range } from "vscode";
import { CSSVarRecord, UNSTABLE_FEATURES } from "../constants";
import { createCompletionItems, getRegion, Region } from "../main";

jest.mock("../constants", () => ({
...jest.requireActual("../constants"),
UNSTABLE_FEATURES: {
no_sort: true,
},
}));

let region: Region | null = null;

describe("Test Extension Main", () => {
beforeEach(() => {
region = getRegion(
"color: --s",
new Range(new Position(0, 5), new Position(0, 10))
);
});

describe(`Test createCompletion method`, () => {
it("Should return CompletionItems with Sorting On", async () => {
UNSTABLE_FEATURES.no_sort = false;
const cssVars: CSSVarRecord = {
"./src/01.css": [
{
property: "--red-A100",
value: "red",
theme: "",
},
],
"./src/02.css": [
{
property: "--red-500",
value: "red",
theme: "",
},
],
};
const items = createCompletionItems(cssVars, {
region,
languageId: "css",
});
expect(items[0]).not.toHaveProperty("sortText");
expect(items[0]).toEqual(
expect.objectContaining({
insertText: "var(--red-A100);",
})
);
});
it("Should return CompletionItems with Sorting Disabled", async () => {
UNSTABLE_FEATURES.no_sort = true;
const cssVars: CSSVarRecord = {
"./src/01.css": [
{
property: "--red-A100",
value: "red",
theme: "",
},
],
"./src/02.css": [
{
property: "--red-500",
value: "red",
theme: "",
},
],
};

const items = createCompletionItems(cssVars, {
region,
languageId: "css",
});
expect(items[1]).toMatchObject({
detail: "Value: red",
documentation: "red",
kind: 5,
label: "--red-500",
insertText: "var(--red-500);",
sortText: "1",
});
});
it("Should return CompletionItems with 3 and 2digit sortText", async () => {
UNSTABLE_FEATURES.no_sort = true;
const cssVars1: CSSVarRecord = Array(11)
.fill([
{
property: "--red-A100",
value: "red",
theme: "",
},
])
.reduce((acc, item, index) => {
acc[`./src/${index}.css`] = item;
return acc;
}, {});
const cssVars2: CSSVarRecord = Array(101)
.fill([
{
property: "--red-A100",
value: "red",
theme: "",
},
])
.reduce((acc, item, index) => {
acc[`./src/${index}.css`] = item;
return acc;
}, {});

const items1 = createCompletionItems(cssVars1, {
region,
languageId: "css",
});
const items2 = createCompletionItems(cssVars2, {
region,
languageId: "css",
});
expect(items1[10]).toMatchObject({
detail: "Value: red",
documentation: "red",
kind: 5,
label: "--red-A100",
sortText: "10",
});
expect(items1[9]).toEqual(
expect.objectContaining({
sortText: "09",
})
);
expect(items2[99]).toEqual(
expect.objectContaining({
sortText: "099",
})
);
expect(items2[100]).toEqual(
expect.objectContaining({
sortText: "100",
})
);
});
});
});
Loading

0 comments on commit 18e4f0e

Please sign in to comment.