Skip to content

Commit d186ac2

Browse files
authored
Merge pull request zignd#50 from allevaton/simplify-codebase
Simplify codebase
2 parents da4b948 + f21dbe6 commit d186ac2

File tree

10 files changed

+71
-226
lines changed

10 files changed

+71
-226
lines changed

src/css-classes-storage.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
'use strict';
2-
31
import CssClassDefinition from './common/css-class-definition';
42

53
class CssClassesStorage {

src/extension.ts

Lines changed: 31 additions & 172 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
'use strict';
2-
31
import * as async from 'async';
42
import * as _ from 'lodash';
53
import * as vscode from 'vscode';
@@ -48,14 +46,13 @@ function cache(): Promise<void> {
4846
return reject(error);
4947
}
5048

51-
uniqueDefinitions = _.uniqBy(definitions, (x) => x.className);
49+
uniqueDefinitions = _.uniqBy(definitions, def => def.className);
5250

53-
console.log('Sumary:');
51+
console.log('Summary:');
5452
console.log(uris.length, 'parseable documents found');
5553
console.log(definitions.length, 'CSS class definitions found');
5654
console.log(uniqueDefinitions.length, 'unique CSS class definitions found');
5755
console.log(failedLogsCount, 'failed attempts to parse. List of the documents:');
58-
console.log(failedLogs);
5956

6057
notifier.notify('zap', 'CSS classes cached (click to cache again)');
6158

@@ -69,96 +66,30 @@ function cache(): Promise<void> {
6966
});
7067
}
7168

72-
export async function activate(context: vscode.ExtensionContext): Promise<void> {
73-
context.subscriptions.push(vscode.commands.registerCommand('html-css-class-completion.cache', async () => {
74-
await cache();
75-
}));
76-
77-
await cache();
78-
79-
context.subscriptions.push(vscode.languages.registerCompletionItemProvider('html', {
69+
function provideCompletionItemsGenerator(languageSelector: string, classMatchRegex: RegExp) {
70+
return vscode.languages.registerCompletionItemProvider(languageSelector, {
8071
provideCompletionItems(document: vscode.TextDocument, position: vscode.Position): vscode.CompletionItem[] {
81-
let start: vscode.Position = new vscode.Position(position.line, 0);
82-
let range: vscode.Range = new vscode.Range(start, position);
83-
let text: string = document.getText(range);
72+
const start: vscode.Position = new vscode.Position(position.line, 0);
73+
const range: vscode.Range = new vscode.Range(start, position);
74+
const text: string = document.getText(range);
8475

8576
// Check if the cursor is on a class attribute and retrieve all the css rules in this class attribute
86-
let rawClasses: RegExpMatchArray = text.match(/class=["|']([\w- ]*$)/);
87-
if (rawClasses === null) {
77+
const rawClasses: RegExpMatchArray = text.match(classMatchRegex);
78+
if (rawClasses.length === 1) {
8879
return [];
8980
}
9081

9182
// Will store the classes found on the class attribute
92-
var classesOnAttribute: string[] = [];
93-
// Regex to extract the classes found of the class attribute
94-
var classesRegex: RegExp = /[ ]*([\w-]*)[ ]*/g;
95-
96-
var item: RegExpExecArray = null;
97-
while ((item = classesRegex.exec(rawClasses[1])) !== null) {
98-
if (item.index === classesRegex.lastIndex) {
99-
classesRegex.lastIndex++;
100-
}
101-
if (item !== null && item.length > 0) {
102-
classesOnAttribute.push(item[1]);
103-
}
104-
}
105-
classesOnAttribute.pop();
83+
let classesOnAttribute = rawClasses[1].split(' ');
10684

10785
// Creates a collection of CompletionItem based on the classes already cached
108-
var completionItems: vscode.CompletionItem[] = [];
109-
for (var i = 0; i < uniqueDefinitions.length; i++) {
110-
completionItems.push(new vscode.CompletionItem(uniqueDefinitions[i].className, vscode.CompletionItemKind.Variable));
111-
}
112-
113-
// Removes from the collection the classes already specified on the class attribute
114-
for (var i = 0; i < classesOnAttribute.length; i++) {
115-
for (var j = 0; j < completionItems.length; j++) {
116-
if (completionItems[j].label === classesOnAttribute[i]) {
117-
completionItems.splice(j, 1);
118-
}
119-
}
120-
}
121-
122-
return completionItems;
123-
}
124-
}));
125-
context.subscriptions.push(vscode.languages.registerCompletionItemProvider('typescriptreact', {
126-
provideCompletionItems(document: vscode.TextDocument, position: vscode.Position): vscode.CompletionItem[] {
127-
let start: vscode.Position = new vscode.Position(position.line, 0);
128-
let range: vscode.Range = new vscode.Range(start, position);
129-
let text: string = document.getText(range);
130-
131-
// Check if the cursor is on a class attribute and retrieve all the css rules in this class attribute
132-
let rawClasses: RegExpMatchArray = text.match(/className=["|']([\w- ]*$)/);
133-
if (rawClasses === null) {
134-
return [];
135-
}
136-
137-
// Will store the classes found on the class attribute
138-
var classesOnAttribute: string[] = [];
139-
// Regex to extract the classes found of the class attribute
140-
var classesRegex: RegExp = /[ ]*([\w-]*)[ ]*/g;
141-
142-
var item: RegExpExecArray = null;
143-
while ((item = classesRegex.exec(rawClasses[1])) !== null) {
144-
if (item.index === classesRegex.lastIndex) {
145-
classesRegex.lastIndex++;
146-
}
147-
if (item !== null && item.length > 0) {
148-
classesOnAttribute.push(item[1]);
149-
}
150-
}
151-
classesOnAttribute.pop();
152-
153-
// Creates a collection of CompletionItem based on the classes already cached
154-
var completionItems: vscode.CompletionItem[] = [];
155-
for (var i = 0; i < uniqueDefinitions.length; i++) {
156-
completionItems.push(new vscode.CompletionItem(uniqueDefinitions[i].className, vscode.CompletionItemKind.Variable));
157-
}
86+
let completionItems = uniqueDefinitions.map(definition => {
87+
return new vscode.CompletionItem(definition.className, vscode.CompletionItemKind.Variable);
88+
});
15889

15990
// Removes from the collection the classes already specified on the class attribute
160-
for (var i = 0; i < classesOnAttribute.length; i++) {
161-
for (var j = 0; j < completionItems.length; j++) {
91+
for (let i = 0; i < classesOnAttribute.length; i++) {
92+
for (let j = 0; j < completionItems.length; j++) {
16293
if (completionItems[j].label === classesOnAttribute[i]) {
16394
completionItems.splice(j, 1);
16495
}
@@ -167,100 +98,28 @@ export async function activate(context: vscode.ExtensionContext): Promise<void>
16798

16899
return completionItems;
169100
}
170-
}));
171-
context.subscriptions.push(vscode.languages.registerCompletionItemProvider('javascript', {
172-
provideCompletionItems(document: vscode.TextDocument, position: vscode.Position): vscode.CompletionItem[] {
173-
let start: vscode.Position = new vscode.Position(position.line, 0);
174-
let range: vscode.Range = new vscode.Range(start, position);
175-
let text: string = document.getText(range);
176-
177-
// Check if the cursor is on a class attribute and retrieve all the css rules in this class attribute
178-
let rawClasses: RegExpMatchArray = text.match(/className=["|']([\w- ]*$)/);
179-
if (rawClasses === null) {
180-
return [];
181-
}
182-
183-
// Will store the classes found on the class attribute
184-
var classesOnAttribute: string[] = [];
185-
// Regex to extract the classes found of the class attribute
186-
var classesRegex: RegExp = /[ ]*([\w-]*)[ ]*/g;
187-
188-
var item: RegExpExecArray = null;
189-
while ((item = classesRegex.exec(rawClasses[1])) !== null) {
190-
if (item.index === classesRegex.lastIndex) {
191-
classesRegex.lastIndex++;
192-
}
193-
if (item !== null && item.length > 0) {
194-
classesOnAttribute.push(item[1]);
195-
}
196-
}
197-
classesOnAttribute.pop();
198-
199-
// Creates a collection of CompletionItem based on the classes already cached
200-
var completionItems: vscode.CompletionItem[] = [];
201-
for (var i = 0; i < uniqueDefinitions.length; i++) {
202-
completionItems.push(new vscode.CompletionItem(uniqueDefinitions[i].className, vscode.CompletionItemKind.Variable));
203-
}
204-
205-
// Removes from the collection the classes already specified on the class attribute
206-
for (var i = 0; i < classesOnAttribute.length; i++) {
207-
for (var j = 0; j < completionItems.length; j++) {
208-
if (completionItems[j].label === classesOnAttribute[i]) {
209-
completionItems.splice(j, 1);
210-
}
211-
}
212-
}
101+
});
102+
}
213103

214-
return completionItems;
215-
}
104+
export async function activate(context: vscode.ExtensionContext): Promise<void> {
105+
context.subscriptions.push(vscode.commands.registerCommand('html-css-class-completion.cache', async () => {
106+
await cache();
216107
}));
217-
context.subscriptions.push(vscode.languages.registerCompletionItemProvider('javascriptreact', {
218-
provideCompletionItems(document: vscode.TextDocument, position: vscode.Position): vscode.CompletionItem[] {
219-
let start: vscode.Position = new vscode.Position(position.line, 0);
220-
let range: vscode.Range = new vscode.Range(start, position);
221-
let text: string = document.getText(range);
222-
223-
// Check if the cursor is on a class attribute and retrieve all the css rules in this class attribute
224-
let rawClasses: RegExpMatchArray = text.match(/className=["|']([\w- ]*$)/);
225-
if (rawClasses === null) {
226-
return [];
227-
}
228108

229-
// Will store the classes found on the class attribute
230-
var classesOnAttribute: string[] = [];
231-
// Regex to extract the classes found of the class attribute
232-
var classesRegex: RegExp = /[ ]*([\w-]*)[ ]*/g;
109+
const htmlRegex = /class=["|']([\w- ]*$)/;
110+
const jsxRegex = /className=["|']([\w- ]*$)/;
233111

234-
235-
var item: RegExpExecArray = null;
236-
while ((item = classesRegex.exec(rawClasses[1])) !== null) {
237-
if (item.index === classesRegex.lastIndex) {
238-
classesRegex.lastIndex++;
239-
}
240-
if (item !== null && item.length > 0) {
241-
classesOnAttribute.push(item[1]);
242-
}
243-
}
244-
classesOnAttribute.pop();
245-
246-
// Creates a collection of CompletionItem based on the classes already cached
247-
var completionItems: vscode.CompletionItem[] = [];
248-
for (var i = 0; i < uniqueDefinitions.length; i++) {
249-
completionItems.push(new vscode.CompletionItem(uniqueDefinitions[i].className, vscode.CompletionItemKind.Variable));
250-
}
112+
const html = provideCompletionItemsGenerator('html', htmlRegex)
113+
const tsReact = provideCompletionItemsGenerator('typescriptreact', jsxRegex);
114+
const js = provideCompletionItemsGenerator('javascript', jsxRegex)
115+
const jsReact = provideCompletionItemsGenerator('javascriptreact', jsxRegex);
251116

252-
// Removes from the collection the classes already specified on the class attribute
253-
for (var i = 0; i < classesOnAttribute.length; i++) {
254-
for (var j = 0; j < completionItems.length; j++) {
255-
if (completionItems[j].label === classesOnAttribute[i]) {
256-
completionItems.splice(j, 1);
257-
}
258-
}
259-
}
117+
context.subscriptions.push(html);
118+
context.subscriptions.push(tsReact);
119+
context.subscriptions.push(js);
120+
context.subscriptions.push(jsReact);
260121

261-
return completionItems;
262-
}
263-
}));
122+
await cache();
264123
}
265124

266125
export function deactivate(): void {

src/fetcher.ts

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,12 @@
1-
'use strict';
2-
31
import * as vscode from 'vscode';
42
import ParseEngineRegistry from './parse-engines/parse-engine-registry';
53

64
class Fetcher {
75
static async findAllParseableDocuments(): Promise<vscode.Uri[]> {
8-
let include: string = ParseEngineRegistry.supportedLanguagesIds.reduce(
9-
(previousValue: string, currentValue: string, currentIndex: number, array: string[]) => {
10-
previousValue += `**/*.${currentValue}`;
11-
if (currentIndex != array.length - 1) {
12-
previousValue += `, `;
13-
}
14-
return previousValue;
15-
}, "");
16-
17-
let exclude: string = 'node_modules/**/node_modules/**/*';
6+
const exclude = 'node_modules/**/*';
7+
const languages = ParseEngineRegistry.supportedLanguagesIds.join(',');
188

19-
let uris = await vscode.workspace.findFiles(include, exclude);
20-
21-
return uris;
9+
return await vscode.workspace.findFiles(`**/*.{${languages}}`, exclude);
2210
}
2311
}
2412

src/notifier.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
'use strict';
2-
31
import * as vscode from 'vscode';
42

53
class Notifier {

src/parse-engine-gateway.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
'use strict';
2-
31
import * as vscode from 'vscode';
42
import CssClassDefinition from './common/css-class-definition';
53
import ParseEngine from './parse-engines/common/parse-engine';
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
import * as css from 'css';
2+
import CssClassDefinition from '../../common/css-class-definition';
3+
4+
export default class CssClassExtractor {
5+
/**
6+
* @description Extracts class names from CSS AST
7+
*/
8+
static extract(ast: css.Stylesheet): CssClassDefinition[] {
9+
// TODO can we make this asynchronous?
10+
11+
const classNameRegex: RegExp = /[.]([\w-]+)/g;
12+
13+
let definitions: CssClassDefinition[] = [];
14+
15+
// go through each of the rules...
16+
ast.stylesheet.rules.forEach((rule: css.Rule) => {
17+
// ...of type rule
18+
if (rule.type === 'rule') {
19+
// go through each of the selectors of the current rule
20+
rule.selectors.forEach((selector: string) => {
21+
let item: RegExpExecArray = null;
22+
23+
while (item = classNameRegex.exec(selector)) {
24+
definitions.push(new CssClassDefinition(item[1]));
25+
}
26+
});
27+
}
28+
});
29+
30+
return definitions;
31+
}
32+
}

src/parse-engines/common/parse-engine.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
'use strict';
2-
31
import * as vscode from 'vscode';
42
import CssClassDefinition from './../../common/css-class-definition';
53

src/parse-engines/parse-engine-registry.ts

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
'use strict';
2-
31
import ParseEngine from './common/parse-engine';
42
import CssParseEngine from './types/css-parse-engine';
53

@@ -11,20 +9,14 @@ class ParseEngineRegistry {
119

1210
public static get supportedLanguagesIds(): string[] {
1311
if (!ParseEngineRegistry._supportedLanguagesIds) {
14-
ParseEngineRegistry._supportedLanguagesIds = ParseEngineRegistry._registry.reduce<string[]>(
15-
(previousValue: string[], currentValue: ParseEngine, currentIndex: number, array: ParseEngine[]) => {
16-
previousValue.push(currentValue.languageId)
17-
return previousValue;
18-
}, []);
12+
ParseEngineRegistry._supportedLanguagesIds = ParseEngineRegistry._registry.map(parseEngine => parseEngine.languageId);
1913
}
2014

2115
return ParseEngineRegistry._supportedLanguagesIds;
2216
}
2317

2418
public static getParseEngine(languageId: string): ParseEngine {
25-
let foundParseEngine: ParseEngine = ParseEngineRegistry._registry.find((value: ParseEngine, index: number, obj: ParseEngine[]) => {
26-
return value.languageId === languageId;
27-
});
19+
let foundParseEngine = ParseEngineRegistry._registry.find(value => value.languageId === languageId);
2820

2921
if (!foundParseEngine) {
3022
throw `Could not find a parse engine for the provided language id ("${languageId}").`;

0 commit comments

Comments
 (0)