@master/css-language-service 2.0.0-rc.7 → 2.0.0-rc.71
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +114 -0
- package/dist/common.d.ts +1 -0
- package/dist/common.mjs +1 -0
- package/dist/core.d.ts +30 -0
- package/dist/core.mjs +114 -0
- package/dist/features/edit-syntax-colors.d.ts +4 -0
- package/dist/features/edit-syntax-colors.mjs +17 -0
- package/dist/features/inspect-syntax.d.ts +4 -0
- package/dist/features/inspect-syntax.mjs +54 -0
- package/dist/features/render-semantic-tokens.d.ts +5 -0
- package/dist/features/render-semantic-tokens.mjs +10 -0
- package/dist/features/render-syntax-colors.d.ts +4 -0
- package/dist/features/render-syntax-colors.mjs +102 -0
- package/dist/features/suggest-syntax.d.ts +5 -0
- package/dist/features/suggest-syntax.mjs +18 -0
- package/dist/index.d.ts +7 -5
- package/dist/index.mjs +7 -0
- package/dist/settings.d.ts +16 -9
- package/dist/settings.mjs +53 -0
- package/dist/utils/beautify-css.d.ts +1 -0
- package/dist/utils/beautify-css.mjs +11 -0
- package/dist/utils/completion-index.d.ts +38 -0
- package/dist/utils/completion-index.mjs +268 -0
- package/dist/utils/convert-color-token.d.ts +4 -0
- package/dist/utils/convert-color-token.mjs +55 -0
- package/dist/utils/create-css-markdown-documentation.d.ts +5 -0
- package/dist/utils/create-css-markdown-documentation.mjs +15 -0
- package/dist/utils/create-doc.d.ts +16 -0
- package/dist/utils/create-doc.mjs +21 -0
- package/dist/utils/get-class-completion-items.d.ts +4 -0
- package/dist/utils/get-class-completion-items.mjs +20 -0
- package/dist/utils/get-color-completion-items.d.ts +3 -0
- package/dist/utils/get-color-completion-items.mjs +24 -0
- package/dist/utils/get-position.d.ts +1 -0
- package/dist/utils/get-position.mjs +10 -0
- package/dist/utils/get-pseudo-class-completion-items.d.ts +4 -0
- package/dist/utils/get-pseudo-class-completion-items.mjs +68 -0
- package/dist/utils/get-pseudo-element-completion-items.d.ts +4 -0
- package/dist/utils/get-pseudo-element-completion-items.mjs +43 -0
- package/dist/utils/get-query-completion-items.d.ts +4 -0
- package/dist/utils/get-query-completion-items.mjs +77 -0
- package/dist/utils/get-range.d.ts +2 -0
- package/dist/utils/get-range.mjs +21 -0
- package/dist/utils/get-utility-info.d.ts +4 -0
- package/dist/utils/get-utility-info.mjs +19 -0
- package/dist/utils/get-value-completion-items.d.ts +4 -0
- package/dist/utils/get-value-completion-items.mjs +203 -0
- package/dist/utils/query-syntax-completions.d.ts +4 -0
- package/dist/utils/query-syntax-completions.mjs +94 -0
- package/dist/utils/regex.mjs +3 -0
- package/dist/utils/sort-completion-items.d.ts +2 -0
- package/dist/utils/sort-completion-items.mjs +11 -0
- package/package.json +1 -1
- package/dist/constant.d.ts +0 -33
- package/dist/index.bundle.js +0 -33
- package/dist/position-check.d.ts +0 -20
- package/dist/providers/color.d.ts +0 -5
- package/dist/providers/completion.d.ts +0 -14
- package/dist/providers/hover.d.ts +0 -2
- package/dist/settings.bundle.js +0 -1
- package/dist/utils/get-css-entry-markdown-description.d.ts +0 -1
- package/dist/utils/hex-to-rgb.d.ts +0 -2
- package/dist/utils/oklab-to-rgb.d.ts +0 -1
- package/dist/utils/oklch-to-oklab.d.ts +0 -1
- package/dist/utils/to-two-digit-hex.d.ts +0 -1
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { type CompletionItem } from 'vscode-languageserver-protocol';
|
|
2
|
+
import { type AtRule, type MasterCSS } from '@master/css-language';
|
|
3
|
+
import type { Variable } from '@master/css-language';
|
|
4
|
+
export interface ClassCompletionEntry extends CompletionItem {
|
|
5
|
+
documentationClassName?: string;
|
|
6
|
+
}
|
|
7
|
+
export interface PatternValueCandidate {
|
|
8
|
+
value: string;
|
|
9
|
+
}
|
|
10
|
+
export interface ScopedVariableCandidate {
|
|
11
|
+
name: string;
|
|
12
|
+
variable: Variable;
|
|
13
|
+
}
|
|
14
|
+
export interface AnimationUtilityCandidate {
|
|
15
|
+
detailPrefix?: string;
|
|
16
|
+
}
|
|
17
|
+
export interface SelectorVariantCandidate {
|
|
18
|
+
token: string;
|
|
19
|
+
selector: string;
|
|
20
|
+
}
|
|
21
|
+
export interface CompletionIndex {
|
|
22
|
+
classEntries: ClassCompletionEntry[];
|
|
23
|
+
componentNames: string[];
|
|
24
|
+
utilityNames: string[];
|
|
25
|
+
nativeUtilityKeys: Map<string, string>;
|
|
26
|
+
scopedVariablesByKey: Map<string, ScopedVariableCandidate[]>;
|
|
27
|
+
patternValuesByKey: Map<string, PatternValueCandidate[]>;
|
|
28
|
+
animationUtilitiesByKey: Map<string, AnimationUtilityCandidate[]>;
|
|
29
|
+
nativeVariableNamespacesByProperty: Map<string, string[]>;
|
|
30
|
+
variables: Variable[];
|
|
31
|
+
pseudoClassNames: string[];
|
|
32
|
+
pseudoClassSelectors: SelectorVariantCandidate[];
|
|
33
|
+
pseudoElementNames: string[];
|
|
34
|
+
pseudoElementSelectors: SelectorVariantCandidate[];
|
|
35
|
+
atRules: [string, AtRule][];
|
|
36
|
+
}
|
|
37
|
+
export declare function createCompletionIndex(css?: MasterCSS): CompletionIndex;
|
|
38
|
+
export declare function matchesIndexedName(field: string, name: string): boolean;
|
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
import { CompletionItemKind } from 'vscode-languageserver-protocol';
|
|
2
|
+
import { builtinNativeValueNamespaces, builtinKeyAliases } from '@master/css-engine';
|
|
3
|
+
import { UtilityType, getMdnPseudoElementNames, getMdnPseudoClassNames, createDefaultCSS } from '@master/css-language';
|
|
4
|
+
import getUtilityInfo from './get-utility-info.mjs';
|
|
5
|
+
import sortCompletionItems from './sort-completion-items.mjs';
|
|
6
|
+
|
|
7
|
+
const ANIMATION_REFERENCE_PROPERTIES = new Set([
|
|
8
|
+
'animation',
|
|
9
|
+
'animation-name'
|
|
10
|
+
]);
|
|
11
|
+
function utilityMayReferenceAnimations(utility) {
|
|
12
|
+
const emit = utility.emit;
|
|
13
|
+
switch(emit.type){
|
|
14
|
+
case 'declarations':
|
|
15
|
+
return emit.declarations.some((property)=>ANIMATION_REFERENCE_PROPERTIES.has(property));
|
|
16
|
+
case 'property':
|
|
17
|
+
return ANIMATION_REFERENCE_PROPERTIES.has(emit.property);
|
|
18
|
+
case 'template':
|
|
19
|
+
return Object.keys(emit.declarations).some((property)=>ANIMATION_REFERENCE_PROPERTIES.has(property));
|
|
20
|
+
case 'static':
|
|
21
|
+
return emit.rules.some((rule)=>Object.keys(rule.declarations).some((property)=>ANIMATION_REFERENCE_PROPERTIES.has(property)));
|
|
22
|
+
default:
|
|
23
|
+
return false;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
function isPureNativePropertyUtility(utility) {
|
|
27
|
+
return utility.emit.type === 'property' && utility.id === utility.emit.property && utility.name === utility.emit.property;
|
|
28
|
+
}
|
|
29
|
+
function addMapValue(map, key, value) {
|
|
30
|
+
const values = map.get(key);
|
|
31
|
+
if (values) {
|
|
32
|
+
values.push(value);
|
|
33
|
+
} else {
|
|
34
|
+
map.set(key, [
|
|
35
|
+
value
|
|
36
|
+
]);
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
function collectClassEntries(css) {
|
|
40
|
+
const completionItems = [];
|
|
41
|
+
const addedKeys = new Set();
|
|
42
|
+
const addedCompletionLabels = new Set();
|
|
43
|
+
const propertyCompletionItem = {
|
|
44
|
+
kind: CompletionItemKind.Property,
|
|
45
|
+
command: {
|
|
46
|
+
title: 'triggerSuggest',
|
|
47
|
+
command: 'editor.action.triggerSuggest'
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
const addPropertyCompletionItem = (key, detail)=>{
|
|
51
|
+
const label = key + ':';
|
|
52
|
+
if (addedCompletionLabels.has(label)) return;
|
|
53
|
+
addedCompletionLabels.add(label);
|
|
54
|
+
completionItems.push({
|
|
55
|
+
...propertyCompletionItem,
|
|
56
|
+
...detail ? {
|
|
57
|
+
detail
|
|
58
|
+
} : {},
|
|
59
|
+
label,
|
|
60
|
+
sortText: key
|
|
61
|
+
});
|
|
62
|
+
};
|
|
63
|
+
const addSemanticCompletionItem = (label, detail)=>{
|
|
64
|
+
if (addedCompletionLabels.has(label)) return;
|
|
65
|
+
addedCompletionLabels.add(label);
|
|
66
|
+
completionItems.push({
|
|
67
|
+
label,
|
|
68
|
+
kind: CompletionItemKind.Value,
|
|
69
|
+
documentationClassName: label,
|
|
70
|
+
...detail ? {
|
|
71
|
+
detail
|
|
72
|
+
} : {}
|
|
73
|
+
});
|
|
74
|
+
};
|
|
75
|
+
for (const eachDefinedUtility of css.definedUtilities){
|
|
76
|
+
if (eachDefinedUtility.type === UtilityType.Semantic) {
|
|
77
|
+
const isComponent = eachDefinedUtility.layer === 'components';
|
|
78
|
+
const { detail } = getUtilityInfo(eachDefinedUtility);
|
|
79
|
+
for (const matcher of eachDefinedUtility.matchers){
|
|
80
|
+
if (matcher.type === 'static') {
|
|
81
|
+
addSemanticCompletionItem(matcher.name, isComponent ? 'component' : detail);
|
|
82
|
+
} else if (matcher.type === 'pattern') {
|
|
83
|
+
for (const value of matcher.values){
|
|
84
|
+
addSemanticCompletionItem(matcher.prefix + value, isComponent ? 'component' : undefined);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
} else {
|
|
89
|
+
for (const matcher of eachDefinedUtility.matchers){
|
|
90
|
+
if (matcher.type !== 'pattern') continue;
|
|
91
|
+
for (const value of matcher.values){
|
|
92
|
+
addSemanticCompletionItem(matcher.prefix + value);
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
eachDefinedUtility.keys?.forEach((key)=>{
|
|
96
|
+
addedKeys.delete(key);
|
|
97
|
+
addPropertyCompletionItem(key);
|
|
98
|
+
});
|
|
99
|
+
if (eachDefinedUtility.aliasGroups?.length) {
|
|
100
|
+
for (const aliasGroup of eachDefinedUtility.aliasGroups){
|
|
101
|
+
if (addedKeys.has(aliasGroup)) {
|
|
102
|
+
continue;
|
|
103
|
+
}
|
|
104
|
+
addedKeys.add(aliasGroup);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
for (const [key, canonicalKey] of Object.entries(builtinKeyAliases)){
|
|
110
|
+
addPropertyCompletionItem(key, canonicalKey);
|
|
111
|
+
}
|
|
112
|
+
for (const namespace of builtinNativeValueNamespaces){
|
|
113
|
+
for (const property of namespace.properties){
|
|
114
|
+
addPropertyCompletionItem(property);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
addedKeys.forEach((aliasGroup)=>{
|
|
118
|
+
/**
|
|
119
|
+
* Ambiguous keys are added to the completion list
|
|
120
|
+
* @example text: t:
|
|
121
|
+
*/ if (addedCompletionLabels.has(aliasGroup + ':')) return;
|
|
122
|
+
completionItems.push({
|
|
123
|
+
...propertyCompletionItem,
|
|
124
|
+
detail: 'ambiguous key',
|
|
125
|
+
label: aliasGroup + ':',
|
|
126
|
+
sortText: aliasGroup
|
|
127
|
+
});
|
|
128
|
+
});
|
|
129
|
+
return sortCompletionItems(completionItems);
|
|
130
|
+
}
|
|
131
|
+
function createPseudoClassSelectors(css) {
|
|
132
|
+
const selectors = new Map([
|
|
133
|
+
[
|
|
134
|
+
':of',
|
|
135
|
+
':of'
|
|
136
|
+
]
|
|
137
|
+
]);
|
|
138
|
+
for (const [token, branches] of css.variants){
|
|
139
|
+
const selector = branches.find((branch)=>branch.selector)?.selector;
|
|
140
|
+
if (selector && token.startsWith(':') && !token.startsWith('::')) {
|
|
141
|
+
selectors.set(token, selector);
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
return Array.from(selectors, ([token, selector])=>({
|
|
145
|
+
token,
|
|
146
|
+
selector
|
|
147
|
+
}));
|
|
148
|
+
}
|
|
149
|
+
function createPseudoElementSelectors(css) {
|
|
150
|
+
const selectors = [];
|
|
151
|
+
for (const [token, branches] of css.variants){
|
|
152
|
+
const selector = branches.find((branch)=>branch.selector)?.selector;
|
|
153
|
+
if (selector && token.startsWith('::')) {
|
|
154
|
+
selectors.push({
|
|
155
|
+
token,
|
|
156
|
+
selector
|
|
157
|
+
});
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
return selectors;
|
|
161
|
+
}
|
|
162
|
+
function createNativeVariableNamespacesByProperty() {
|
|
163
|
+
const namespacesByProperty = new Map();
|
|
164
|
+
for (const namespace of builtinNativeValueNamespaces){
|
|
165
|
+
const variableNamespaces = (namespace.variableAliasRefs || []).map((ref)=>ref[0] === '=' || ref[0] === '~' ? ref.slice(1) : '').filter(Boolean);
|
|
166
|
+
if (!variableNamespaces.length) continue;
|
|
167
|
+
for (const property of namespace.properties){
|
|
168
|
+
const namespaces = namespacesByProperty.get(property);
|
|
169
|
+
if (namespaces) {
|
|
170
|
+
namespaces.push(...variableNamespaces);
|
|
171
|
+
} else {
|
|
172
|
+
namespacesByProperty.set(property, [
|
|
173
|
+
...variableNamespaces
|
|
174
|
+
]);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
return namespacesByProperty;
|
|
179
|
+
}
|
|
180
|
+
function createCompletionIndex(css = createDefaultCSS()) {
|
|
181
|
+
const componentNames = [];
|
|
182
|
+
const utilityNames = [];
|
|
183
|
+
const nativeUtilityKeys = new Map();
|
|
184
|
+
const scopedVariablesByKey = new Map();
|
|
185
|
+
const patternValuesByKey = new Map();
|
|
186
|
+
const animationUtilitiesByKey = new Map();
|
|
187
|
+
for (const utility of css.definedUtilities){
|
|
188
|
+
const staticNames = utility.type === UtilityType.Semantic ? utilityNames : undefined;
|
|
189
|
+
for (const matcher of utility.matchers){
|
|
190
|
+
if (matcher.type === 'static') {
|
|
191
|
+
staticNames?.push(matcher.name);
|
|
192
|
+
if (utility.type === UtilityType.Semantic && utility.layer === 'components') {
|
|
193
|
+
componentNames.push(matcher.name);
|
|
194
|
+
}
|
|
195
|
+
} else if (matcher.type === 'pattern') {
|
|
196
|
+
const patternNames = matcher.values.map((value)=>matcher.prefix + value);
|
|
197
|
+
utilityNames.push(...patternNames);
|
|
198
|
+
if (utility.type === UtilityType.Semantic && utility.layer === 'components') {
|
|
199
|
+
componentNames.push(...patternNames);
|
|
200
|
+
}
|
|
201
|
+
if (matcher.prefix.endsWith(':')) {
|
|
202
|
+
const key = matcher.prefix.slice(0, -1);
|
|
203
|
+
for (const value of matcher.values){
|
|
204
|
+
addMapValue(patternValuesByKey, key, {
|
|
205
|
+
value
|
|
206
|
+
});
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
for (const key of utility.keys || []){
|
|
212
|
+
if (!nativeUtilityKeys.has(key)) {
|
|
213
|
+
nativeUtilityKeys.set(key, utility.emit.type === 'property' ? utility.emit.property : utility.id);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
if (utility.variables?.size) {
|
|
217
|
+
const keys = new Set([
|
|
218
|
+
utility.key,
|
|
219
|
+
utility.subkey,
|
|
220
|
+
...utility.keys || [],
|
|
221
|
+
...utility.aliasGroups || []
|
|
222
|
+
].filter((key)=>Boolean(key)));
|
|
223
|
+
for (const key of keys){
|
|
224
|
+
utility.variables.forEach((variable, name)=>{
|
|
225
|
+
addMapValue(scopedVariablesByKey, key, {
|
|
226
|
+
name,
|
|
227
|
+
variable
|
|
228
|
+
});
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
if (utility.keys?.length && utilityMayReferenceAnimations(utility)) {
|
|
233
|
+
const detailPrefix = isPureNativePropertyUtility(utility) ? utility.id : undefined;
|
|
234
|
+
for (const key of utility.keys){
|
|
235
|
+
addMapValue(animationUtilitiesByKey, key, {
|
|
236
|
+
detailPrefix
|
|
237
|
+
});
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
return {
|
|
242
|
+
classEntries: collectClassEntries(css),
|
|
243
|
+
componentNames,
|
|
244
|
+
utilityNames,
|
|
245
|
+
nativeUtilityKeys,
|
|
246
|
+
scopedVariablesByKey,
|
|
247
|
+
patternValuesByKey,
|
|
248
|
+
animationUtilitiesByKey,
|
|
249
|
+
nativeVariableNamespacesByProperty: createNativeVariableNamespacesByProperty(),
|
|
250
|
+
variables: Array.from(css.variables.values()),
|
|
251
|
+
pseudoClassNames: getMdnPseudoClassNames(),
|
|
252
|
+
pseudoClassSelectors: createPseudoClassSelectors(css),
|
|
253
|
+
pseudoElementNames: getMdnPseudoElementNames(),
|
|
254
|
+
pseudoElementSelectors: createPseudoElementSelectors(css),
|
|
255
|
+
atRules: Array.from(css.atRules.entries())
|
|
256
|
+
};
|
|
257
|
+
}
|
|
258
|
+
function matchesIndexedName(field, name) {
|
|
259
|
+
if (!field.startsWith(name)) return false;
|
|
260
|
+
const nextCharacter = field.charAt(name.length);
|
|
261
|
+
if (nextCharacter === '_') return true;
|
|
262
|
+
const lastCharacter = name.charAt(name.length - 1);
|
|
263
|
+
const lastIsWord = /\w/.test(lastCharacter);
|
|
264
|
+
const nextIsWord = /\w/.test(nextCharacter);
|
|
265
|
+
return lastIsWord !== nextIsWord;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
export { createCompletionIndex, matchesIndexedName };
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { MasterCSS } from '@master/css-language';
|
|
2
|
+
import type { ColorPresentationParams } from 'vscode-languageserver-protocol';
|
|
3
|
+
export default function convertColorByToken(color: ColorPresentationParams['color'], colorToken: string, css: MasterCSS): string | undefined;
|
|
4
|
+
export declare function normalizeCSSColorFunctionName(fn: string): string;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import Color from 'colorjs.io';
|
|
2
|
+
|
|
3
|
+
function convertColorByToken(color, colorToken, css) {
|
|
4
|
+
const valueComponent = css.generate('color:' + colorToken)[0]?.valueComponents[0];
|
|
5
|
+
let outputSpace = 'srgb';
|
|
6
|
+
switch(valueComponent?.type){
|
|
7
|
+
case 'function':
|
|
8
|
+
outputSpace = valueComponent.name;
|
|
9
|
+
break;
|
|
10
|
+
case 'variable':
|
|
11
|
+
outputSpace = String(valueComponent.variable?.value || '').match(/^([a-zA-Z][\w-]*)\(/)?.[1] || outputSpace;
|
|
12
|
+
break;
|
|
13
|
+
case 'string':
|
|
14
|
+
outputSpace = 'srgb';
|
|
15
|
+
break;
|
|
16
|
+
}
|
|
17
|
+
outputSpace = normalizeCSSColorFunctionName(outputSpace);
|
|
18
|
+
if (!outputSpace) {
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
return new Color({
|
|
22
|
+
space: 'srgb',
|
|
23
|
+
coords: [
|
|
24
|
+
color.red,
|
|
25
|
+
color.green,
|
|
26
|
+
color.blue
|
|
27
|
+
],
|
|
28
|
+
alpha: color.alpha
|
|
29
|
+
}).to(outputSpace).toString({
|
|
30
|
+
format: 'css',
|
|
31
|
+
precision: 4,
|
|
32
|
+
inGamut: false
|
|
33
|
+
}).replace(' / ', '/').replaceAll(' ', '|');
|
|
34
|
+
}
|
|
35
|
+
function normalizeCSSColorFunctionName(fn) {
|
|
36
|
+
switch(fn){
|
|
37
|
+
case 'rgb':
|
|
38
|
+
case 'rgba':
|
|
39
|
+
return 'srgb';
|
|
40
|
+
case 'hsla':
|
|
41
|
+
return 'hsl';
|
|
42
|
+
case 'display-p3':
|
|
43
|
+
case 'p3':
|
|
44
|
+
return 'p3';
|
|
45
|
+
case 'rec2020':
|
|
46
|
+
case 'rec.2020':
|
|
47
|
+
return 'rec2020';
|
|
48
|
+
case 'color':
|
|
49
|
+
return '';
|
|
50
|
+
default:
|
|
51
|
+
return fn;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
export { convertColorByToken as default, normalizeCSSColorFunctionName };
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import beautifyCSS from './beautify-css.mjs';
|
|
2
|
+
|
|
3
|
+
function createCSSMarkdownDocumentation(css) {
|
|
4
|
+
if (!css) return;
|
|
5
|
+
const cssLines = beautifyCSS(css).split('\n');
|
|
6
|
+
if (cssLines[0] === '') {
|
|
7
|
+
cssLines.shift();
|
|
8
|
+
}
|
|
9
|
+
return {
|
|
10
|
+
kind: 'markdown',
|
|
11
|
+
value: '```css\n' + cssLines.join('\n') + '\n```'
|
|
12
|
+
};
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export { createCSSMarkdownDocumentation as default };
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { TextDocument } from 'vscode-languageserver-textdocument';
|
|
2
|
+
export declare const languageIdOfExt: {
|
|
3
|
+
ts: string;
|
|
4
|
+
tsx: string;
|
|
5
|
+
js: string;
|
|
6
|
+
jsx: string;
|
|
7
|
+
css: string;
|
|
8
|
+
scss: string;
|
|
9
|
+
less: string;
|
|
10
|
+
html: string;
|
|
11
|
+
json: string;
|
|
12
|
+
vue: string;
|
|
13
|
+
svelte: string;
|
|
14
|
+
astro: string;
|
|
15
|
+
};
|
|
16
|
+
export default function createDoc(ext: keyof typeof languageIdOfExt, content: string): TextDocument;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { TextDocument } from 'vscode-languageserver-textdocument';
|
|
2
|
+
|
|
3
|
+
const languageIdOfExt = {
|
|
4
|
+
ts: 'typescript',
|
|
5
|
+
tsx: 'typescriptreact',
|
|
6
|
+
js: 'javascript',
|
|
7
|
+
jsx: 'javascriptreact',
|
|
8
|
+
css: 'css',
|
|
9
|
+
scss: 'scss',
|
|
10
|
+
less: 'less',
|
|
11
|
+
html: 'html',
|
|
12
|
+
json: 'json',
|
|
13
|
+
vue: 'vue',
|
|
14
|
+
svelte: 'svelte',
|
|
15
|
+
astro: 'astro'
|
|
16
|
+
};
|
|
17
|
+
function createDoc(ext, content) {
|
|
18
|
+
return TextDocument.create(`file:///abc.${ext}`, languageIdOfExt[ext], 0, content);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
export { createDoc as default, languageIdOfExt };
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { type CompletionItem } from 'vscode-languageserver-protocol';
|
|
2
|
+
import { MasterCSS } from '@master/css-language';
|
|
3
|
+
import { type CompletionIndex } from './completion-index';
|
|
4
|
+
export default function getClassCompletionItems(css?: MasterCSS, completionIndex?: CompletionIndex): CompletionItem[];
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { createDefaultCSS, generateCSS } from '@master/css-language';
|
|
2
|
+
import createCSSMarkdownDocumentation from './create-css-markdown-documentation.mjs';
|
|
3
|
+
import { createCompletionIndex } from './completion-index.mjs';
|
|
4
|
+
|
|
5
|
+
function createCompletionItem(css, entry) {
|
|
6
|
+
const { documentationClassName, ...completionItem } = entry;
|
|
7
|
+
return {
|
|
8
|
+
...completionItem,
|
|
9
|
+
...documentationClassName ? {
|
|
10
|
+
documentation: createCSSMarkdownDocumentation(generateCSS([
|
|
11
|
+
documentationClassName
|
|
12
|
+
], css))
|
|
13
|
+
} : {}
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
function getClassCompletionItems(css = createDefaultCSS(), completionIndex = createCompletionIndex(css)) {
|
|
17
|
+
return completionIndex.classEntries.map((entry)=>createCompletionItem(css, entry));
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export { getClassCompletionItems as default };
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { createDefaultCSS } from '@master/css-language';
|
|
2
|
+
import { CompletionItemKind } from 'vscode-languageserver-protocol';
|
|
3
|
+
import sortCompletionItems from './sort-completion-items.mjs';
|
|
4
|
+
|
|
5
|
+
function getColorCompletionItems(css = createDefaultCSS()) {
|
|
6
|
+
const completionItems = [];
|
|
7
|
+
css.variables.forEach((eachVariable, eachVariableName)=>{
|
|
8
|
+
if (eachVariable.namespace?.startsWith('color')) {
|
|
9
|
+
const valueToken = eachVariable.value ?? eachVariable.name;
|
|
10
|
+
completionItems.push({
|
|
11
|
+
label: eachVariableName,
|
|
12
|
+
// detail is shown in the detail pane
|
|
13
|
+
detail: String(valueToken),
|
|
14
|
+
// documentation is shown in the hover
|
|
15
|
+
documentation: String(valueToken),
|
|
16
|
+
kind: CompletionItemKind.Color,
|
|
17
|
+
sortText: eachVariableName.replace(/(.+?)-(\d+)/, (match, prefix, num)=>prefix + '-' + ('00000' + num).slice(-5))
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
});
|
|
21
|
+
return sortCompletionItems(completionItems);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export { getColorCompletionItems as default };
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export default function getPosition(searchString: string, text: string): import("vscode-languageserver-textdocument").Position;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { TextDocument } from 'vscode-languageserver-textdocument';
|
|
2
|
+
|
|
3
|
+
function getPosition(searchString, text) {
|
|
4
|
+
const document = TextDocument.create('mockuri://test', 'plaintext', 1, text);
|
|
5
|
+
const offset = text.indexOf(searchString);
|
|
6
|
+
const position = document.positionAt(offset);
|
|
7
|
+
return position;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export { getPosition as default };
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { MasterCSS } from '@master/css-language';
|
|
2
|
+
import { type CompletionItem } from 'vscode-languageserver-protocol';
|
|
3
|
+
import { type CompletionIndex } from './completion-index';
|
|
4
|
+
export default function getPseudoClassCompletionItems(css: MasterCSS | undefined, syntax: string, completionIndex?: CompletionIndex): CompletionItem[];
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { generateCSS, createDefaultCSS } from '@master/css-language';
|
|
2
|
+
import { CompletionItemKind } from 'vscode-languageserver-protocol';
|
|
3
|
+
import sortCompletionItems from './sort-completion-items.mjs';
|
|
4
|
+
import createCSSMarkdownDocumentation from './create-css-markdown-documentation.mjs';
|
|
5
|
+
import { createCompletionIndex } from './completion-index.mjs';
|
|
6
|
+
|
|
7
|
+
const kind = CompletionItemKind.Function;
|
|
8
|
+
const functionalPseudoClassNames = new Set([
|
|
9
|
+
':current',
|
|
10
|
+
':dir',
|
|
11
|
+
':has',
|
|
12
|
+
':has-slotted',
|
|
13
|
+
':host',
|
|
14
|
+
':host-context',
|
|
15
|
+
':is',
|
|
16
|
+
':lang',
|
|
17
|
+
':local-link',
|
|
18
|
+
':not',
|
|
19
|
+
':nth',
|
|
20
|
+
':nth-child',
|
|
21
|
+
':nth-col',
|
|
22
|
+
':nth-last',
|
|
23
|
+
':nth-last-child',
|
|
24
|
+
':nth-last-col',
|
|
25
|
+
':nth-last-of-type',
|
|
26
|
+
':nth-of-type',
|
|
27
|
+
':of',
|
|
28
|
+
':state',
|
|
29
|
+
':where'
|
|
30
|
+
]);
|
|
31
|
+
function normalizeFunctionalPseudoClass(name) {
|
|
32
|
+
return functionalPseudoClassNames.has(name) ? name + '()' : name;
|
|
33
|
+
}
|
|
34
|
+
function getPseudoClassCompletionItems(css = createDefaultCSS(), syntax, completionIndex = createCompletionIndex(css)) {
|
|
35
|
+
const completionItems = completionIndex.pseudoClassNames.map((pseudoClassName)=>{
|
|
36
|
+
const name = normalizeFunctionalPseudoClass(pseudoClassName);
|
|
37
|
+
let sortText = name.startsWith(':-') ? 'yyyy' + name.slice(2) : 'yy' + name.replace(/^:/, '');
|
|
38
|
+
if (sortText.endsWith('()')) sortText = 'y' + sortText;
|
|
39
|
+
return {
|
|
40
|
+
label: name,
|
|
41
|
+
sortText,
|
|
42
|
+
documentation: createCSSMarkdownDocumentation(generateCSS([
|
|
43
|
+
syntax + name.slice(1)
|
|
44
|
+
], css)),
|
|
45
|
+
kind
|
|
46
|
+
};
|
|
47
|
+
});
|
|
48
|
+
for (const { token: name, selector } of completionIndex.pseudoClassSelectors){
|
|
49
|
+
if (name.startsWith('::')) continue;
|
|
50
|
+
const value = selector.replace(/&/g, '');
|
|
51
|
+
const label = normalizeFunctionalPseudoClass(name);
|
|
52
|
+
let sortText = label.startsWith(':-') ? 'yyyy' + label.slice(2) : 'yy' + label.replace(/^:/, '');
|
|
53
|
+
if (sortText.endsWith('()')) sortText = 'y' + sortText;
|
|
54
|
+
const completionItem = {
|
|
55
|
+
label,
|
|
56
|
+
documentation: createCSSMarkdownDocumentation(generateCSS([
|
|
57
|
+
syntax + label.slice(1)
|
|
58
|
+
], css)),
|
|
59
|
+
sortText,
|
|
60
|
+
kind,
|
|
61
|
+
detail: String(value)
|
|
62
|
+
};
|
|
63
|
+
completionItems.push(completionItem);
|
|
64
|
+
}
|
|
65
|
+
return sortCompletionItems(completionItems);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export { getPseudoClassCompletionItems as default };
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { MasterCSS } from '@master/css-language';
|
|
2
|
+
import { type CompletionItem } from 'vscode-languageserver-protocol';
|
|
3
|
+
import { type CompletionIndex } from './completion-index';
|
|
4
|
+
export default function getPseudoElementCompletionItems(css: MasterCSS | undefined, syntax: string, completionIndex?: CompletionIndex): CompletionItem[];
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { generateCSS, createDefaultCSS } from '@master/css-language';
|
|
2
|
+
import { CompletionItemKind } from 'vscode-languageserver-protocol';
|
|
3
|
+
import sortCompletionItems from './sort-completion-items.mjs';
|
|
4
|
+
import createCSSMarkdownDocumentation from './create-css-markdown-documentation.mjs';
|
|
5
|
+
import { createCompletionIndex } from './completion-index.mjs';
|
|
6
|
+
|
|
7
|
+
const kind = CompletionItemKind.Function;
|
|
8
|
+
function getPseudoElementCompletionItems(css = createDefaultCSS(), syntax, completionIndex = createCompletionIndex(css)) {
|
|
9
|
+
const completionItems = completionIndex.pseudoElementNames.map((pseudoElementName)=>{
|
|
10
|
+
const name = /::(?:part|slotted)/.test(pseudoElementName) ? pseudoElementName + '()' : pseudoElementName;
|
|
11
|
+
let sortText = name.startsWith('::-') ? 'zzzz' + name.slice(3) : 'zz' + name.replace(/^::/, '');
|
|
12
|
+
if (sortText.endsWith('()')) sortText = 'z' + sortText;
|
|
13
|
+
return {
|
|
14
|
+
label: name,
|
|
15
|
+
sortText,
|
|
16
|
+
documentation: createCSSMarkdownDocumentation(generateCSS([
|
|
17
|
+
syntax + name.slice(2)
|
|
18
|
+
], css)),
|
|
19
|
+
kind
|
|
20
|
+
};
|
|
21
|
+
});
|
|
22
|
+
for (const variant of completionIndex.pseudoElementSelectors){
|
|
23
|
+
const selectorName = variant.token;
|
|
24
|
+
const selectorValue = variant.selector.replace(/&/g, '');
|
|
25
|
+
const name = selectorName.endsWith('(') ? selectorName + ')' : selectorName;
|
|
26
|
+
const value = typeof selectorValue === 'string' ? selectorValue.endsWith('(') ? selectorValue + ')' : selectorValue : selectorValue;
|
|
27
|
+
let sortText = name.startsWith('::-') ? 'zzzz' + name.slice(3) : 'zz' + name.replace(/^::/, '');
|
|
28
|
+
if (sortText.endsWith('()')) sortText = 'z' + sortText;
|
|
29
|
+
const completionItem = {
|
|
30
|
+
label: name,
|
|
31
|
+
documentation: createCSSMarkdownDocumentation(generateCSS([
|
|
32
|
+
syntax + name.slice(2)
|
|
33
|
+
], css)),
|
|
34
|
+
sortText,
|
|
35
|
+
kind,
|
|
36
|
+
detail: String(value)
|
|
37
|
+
};
|
|
38
|
+
completionItems.push(completionItem);
|
|
39
|
+
}
|
|
40
|
+
return sortCompletionItems(completionItems);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export { getPseudoElementCompletionItems as default };
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import { MasterCSS } from '@master/css-language';
|
|
2
|
+
import { CompletionItem } from 'vscode-languageserver-protocol';
|
|
3
|
+
import { type CompletionIndex } from './completion-index';
|
|
4
|
+
export default function getQueryCompletionItems(css: MasterCSS | undefined, triggerCharacter: string | undefined, syntax: string, completionIndex?: CompletionIndex): CompletionItem[];
|