Skip to content

Commit 466266f

Browse files
committed
Fixes
1 parent e56d9ad commit 466266f

File tree

1 file changed

+152
-152
lines changed

1 file changed

+152
-152
lines changed

src/extension.ts

Lines changed: 152 additions & 152 deletions
Original file line numberDiff line numberDiff line change
@@ -1,173 +1,173 @@
11
import fetch from "node-fetch";
22
import { parse, walk } from "css-tree";
33
import {
4-
languages,
5-
Range,
6-
workspace,
7-
ExtensionContext,
8-
CompletionItemProvider,
9-
TextDocument,
10-
Position,
11-
CancellationToken,
12-
CompletionContext,
13-
ProviderResult,
14-
CompletionItem,
15-
CompletionList,
16-
CompletionItemKind
4+
languages,
5+
Range,
6+
workspace,
7+
ExtensionContext,
8+
CompletionItemProvider,
9+
TextDocument,
10+
Position,
11+
CancellationToken,
12+
CompletionContext,
13+
ProviderResult,
14+
CompletionItem,
15+
CompletionList,
16+
CompletionItemKind
1717
} from "vscode";
1818

1919
const NONE = "__!NONE!__";
2020

2121
export class ClassCompletionItemProvider implements CompletionItemProvider {
2222

23-
readonly start = new Position(0, 0);
24-
readonly cache = new Map<string, Map<string, CompletionItem>>();
25-
readonly canComplete = /class\s*=\s*(["'])(?:(?!\1).)*$/si;
26-
readonly findLinkRel = /rel\s*=\s*(["'])((?:(?!\1).)+)\1/si;
27-
readonly findLinkHref = /href\s*=\s*(["'])((?:(?!\1).)+)\1/si;
28-
29-
remoteStyleSheets: string[] = [];
30-
31-
parseTextToItems(text: string, items: Map<string, CompletionItem>) {
32-
walk(parse(text), v => {
33-
if (v.type === "ClassSelector") {
34-
items.set(v.name, new CompletionItem(v.name, CompletionItemKind.EnumMember));
35-
}
36-
});
37-
}
38-
39-
fetchRemoteStyleSheet(key: string): Thenable<string> {
40-
return new Promise(resolve => {
41-
42-
if (key === NONE) {
43-
resolve(NONE);
44-
} else {
45-
const items = this.cache.get(key);
46-
47-
if (items) {
48-
resolve(key);
49-
} else {
50-
const items = new Map<string, CompletionItem>();
51-
52-
fetch(key).then(res => {
53-
if (res.ok) {
54-
res.text().then(text => {
55-
this.parseTextToItems(text, items);
56-
this.cache.set(key, items);
57-
resolve(key);
58-
}, () => resolve(NONE));
59-
} else {
60-
this.cache.set(key, items);
61-
resolve(key);
62-
}
63-
}, () => resolve(NONE));
64-
}
65-
}
66-
});
67-
}
68-
69-
findDocumentLinks(text: string): Thenable<Set<string>> {
70-
return new Promise(resolve => {
71-
const findLinks = /<link([^>]+)>/gi;
72-
const keys = new Set<string>();
73-
const promises = [];
74-
75-
let link;
76-
77-
while ((link = findLinks.exec(text)) !== null) {
78-
const rel = this.findLinkRel.exec(link[1]);
79-
80-
if (rel && rel[2] === "stylesheet") {
81-
const href = this.findLinkHref.exec(link[1]);
82-
83-
if (href && href[2].startsWith("http")) {
84-
promises.push(this.fetchRemoteStyleSheet(href[2]).then(k => keys.add(k)));
85-
}
86-
}
87-
}
88-
89-
Promise.all(promises).then(() => resolve(keys));
90-
});
91-
}
92-
93-
findRemoteStyles(): Thenable<Set<string>> {
94-
return new Promise(resolve => {
95-
const keys = new Set<string>();
96-
const promises = [];
97-
98-
for (const sheet of this.remoteStyleSheets) {
99-
promises.push(this.fetchRemoteStyleSheet(sheet).then(k => keys.add(k)));
100-
}
101-
102-
Promise.all(promises).then(() => resolve(keys));
103-
});
104-
}
105-
106-
findDocumentStyles(text: string): Map<string, CompletionItem> {
107-
const items = new Map<string, CompletionItem>();
108-
const findStyles = /<style[^>]*>([^<]+)<\/style>/gi;
109-
110-
let style;
111-
112-
while ((style = findStyles.exec(text)) !== null) {
113-
this.parseTextToItems(style[1], items);
114-
}
115-
116-
return items;
117-
}
118-
119-
buildItems(items: Map<string, CompletionItem>, ...sets: Set<string>[]): CompletionItem[] {
120-
const keys = new Set<string>();
121-
sets.forEach(v => v.forEach(v => keys.add(v)));
122-
keys.forEach(k => this.cache.get(k)?.forEach((v, k) => items.set(k, v)));
123-
124-
return [...items.values()];
125-
}
126-
127-
provideCompletionItems(
128-
document: TextDocument,
129-
position: Position,
130-
token: CancellationToken,
131-
context: CompletionContext): ProviderResult<CompletionItem[] | CompletionList<CompletionItem>> {
132-
133-
return new Promise((resolve, reject) => {
134-
if (token.isCancellationRequested) {
135-
reject();
136-
} else {
137-
const range = new Range(this.start, position);
138-
const text = document.getText(range);
139-
const canComplete = this.canComplete.test(text);
140-
141-
if (canComplete) {
142-
const items = this.findDocumentStyles(text);
143-
144-
this.findRemoteStyles().then(styles =>
145-
this.findDocumentLinks(text).then(links =>
146-
resolve(this.buildItems(items, styles, links))));
147-
} else {
148-
reject();
149-
}
150-
}
151-
});
152-
}
23+
readonly start = new Position(0, 0);
24+
readonly cache = new Map<string, Map<string, CompletionItem>>();
25+
readonly canComplete = /class\s*=\s*(["'])(?:(?!\1).)*$/si;
26+
readonly findLinkRel = /rel\s*=\s*(["'])((?:(?!\1).)+)\1/si;
27+
readonly findLinkHref = /href\s*=\s*(["'])((?:(?!\1).)+)\1/si;
28+
29+
remoteStyleSheets: string[] = [];
30+
31+
parseTextToItems(text: string, items: Map<string, CompletionItem>) {
32+
walk(parse(text), node => {
33+
if (node.type === "ClassSelector") {
34+
items.set(node.name, new CompletionItem(node.name, CompletionItemKind.EnumMember));
35+
}
36+
});
37+
}
38+
39+
fetchRemoteStyleSheet(key: string): Thenable<string> {
40+
return new Promise(resolve => {
41+
if (key === NONE) {
42+
resolve(NONE);
43+
} else {
44+
const items = this.cache.get(key);
45+
46+
if (items) {
47+
resolve(key);
48+
} else {
49+
const items = new Map<string, CompletionItem>();
50+
51+
fetch(key).then(res => {
52+
if (res.ok) {
53+
res.text().then(text => {
54+
this.parseTextToItems(text, items);
55+
this.cache.set(key, items);
56+
resolve(key);
57+
}, () => resolve(NONE));
58+
} else {
59+
this.cache.set(key, items);
60+
resolve(key);
61+
}
62+
}, () => resolve(NONE));
63+
}
64+
}
65+
});
66+
}
67+
68+
findDocumentLinks(text: string): Thenable<Set<string>> {
69+
return new Promise(resolve => {
70+
const findLinks = /<link([^>]+)>/gi;
71+
const keys = new Set<string>();
72+
const promises = [];
73+
74+
let link;
75+
76+
while ((link = findLinks.exec(text)) !== null) {
77+
const rel = this.findLinkRel.exec(link[1]);
78+
79+
if (rel && rel[2] === "stylesheet") {
80+
const href = this.findLinkHref.exec(link[1]);
81+
82+
if (href && href[2].startsWith("http")) {
83+
promises.push(this.fetchRemoteStyleSheet(href[2]).then(k => keys.add(k)));
84+
}
85+
}
86+
}
87+
88+
Promise.all(promises).then(() => resolve(keys));
89+
});
90+
}
91+
92+
findRemoteStyles(): Thenable<Set<string>> {
93+
return new Promise(resolve => {
94+
const keys = new Set<string>();
95+
const promises = [];
96+
97+
for (const sheet of this.remoteStyleSheets) {
98+
promises.push(this.fetchRemoteStyleSheet(sheet).then(k => keys.add(k)));
99+
}
100+
101+
Promise.all(promises).then(() => resolve(keys));
102+
});
103+
}
104+
105+
findDocumentStyles(text: string): Map<string, CompletionItem> {
106+
const items = new Map<string, CompletionItem>();
107+
const findStyles = /<style[^>]*>([^<]+)<\/style>/gi;
108+
109+
let style;
110+
111+
while ((style = findStyles.exec(text)) !== null) {
112+
this.parseTextToItems(style[1], items);
113+
}
114+
115+
return items;
116+
}
117+
118+
buildItems(items: Map<string, CompletionItem>, ...sets: Set<string>[]): CompletionItem[] {
119+
const keys = new Set<string>();
120+
121+
sets.forEach(v => v.forEach(v => keys.add(v)));
122+
keys.forEach(k => this.cache.get(k)?.forEach((v, k) => items.set(k, v)));
123+
124+
return [...items.values()];
125+
}
126+
127+
provideCompletionItems(
128+
document: TextDocument,
129+
position: Position,
130+
token: CancellationToken,
131+
context: CompletionContext): ProviderResult<CompletionItem[] | CompletionList<CompletionItem>> {
132+
133+
return new Promise((resolve, reject) => {
134+
if (token.isCancellationRequested) {
135+
reject();
136+
} else {
137+
const range = new Range(this.start, position);
138+
const text = document.getText(range);
139+
const canComplete = this.canComplete.test(text);
140+
141+
if (canComplete) {
142+
const items = this.findDocumentStyles(text);
143+
144+
this.findRemoteStyles().then(styles =>
145+
this.findDocumentLinks(text).then(links =>
146+
resolve(this.buildItems(items, styles, links))));
147+
} else {
148+
reject();
149+
}
150+
}
151+
});
152+
}
153153
}
154154

155155
function parseConfig(provider: ClassCompletionItemProvider) {
156-
const config = workspace.getConfiguration("css");
157-
const remoteStyleSheets = config.get<string[]>("remoteStyleSheets");
156+
const config = workspace.getConfiguration("css");
157+
const remoteStyleSheets = config.get<string[]>("remoteStyleSheets");
158158

159-
if (remoteStyleSheets) {
160-
provider.remoteStyleSheets = remoteStyleSheets;
161-
}
159+
if (remoteStyleSheets) {
160+
provider.remoteStyleSheets = remoteStyleSheets;
161+
}
162162
}
163163

164164
export function activate(context: ExtensionContext) {
165-
const provider = new ClassCompletionItemProvider();
165+
const provider = new ClassCompletionItemProvider();
166166

167-
parseConfig(provider);
167+
parseConfig(provider);
168168

169-
context.subscriptions.push(workspace.onDidChangeConfiguration(e => parseConfig(provider)));
170-
context.subscriptions.push(languages.registerCompletionItemProvider("html", provider, "\"", "'"));
169+
context.subscriptions.push(workspace.onDidChangeConfiguration(e => parseConfig(provider)));
170+
context.subscriptions.push(languages.registerCompletionItemProvider("html", provider, "\"", "'"));
171171
}
172172

173173
export function deactivate() { }

0 commit comments

Comments
 (0)