@master/css-language-service 2.0.0-rc.69 → 2.0.0-rc.70
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 +57 -6
- package/dist/common.d.ts +1 -9
- package/dist/common.mjs +1 -48
- package/dist/core.d.ts +11 -10
- package/dist/core.mjs +70 -200
- package/dist/features/inspect-syntax.mjs +18 -32
- 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.mjs +23 -8
- package/dist/features/suggest-syntax.d.ts +2 -1
- package/dist/features/suggest-syntax.mjs +2 -2
- package/dist/index.mjs +1 -1
- package/dist/settings.d.ts +4 -7
- package/dist/settings.mjs +12 -41
- package/dist/utils/beautify-css.mjs +1 -1
- 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 +1 -1
- package/dist/utils/convert-color-token.mjs +1 -1
- package/dist/utils/create-css-markdown-documentation.d.ts +5 -0
- package/dist/utils/create-css-markdown-documentation.mjs +15 -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 +1 -1
- package/dist/utils/get-color-completion-items.mjs +6 -9
- package/dist/utils/get-pseudo-class-completion-items.d.ts +3 -2
- package/dist/utils/get-pseudo-class-completion-items.mjs +45 -42
- package/dist/utils/get-pseudo-element-completion-items.d.ts +3 -2
- package/dist/utils/get-pseudo-element-completion-items.mjs +17 -28
- package/dist/utils/get-query-completion-items.d.ts +3 -2
- package/dist/utils/get-query-completion-items.mjs +19 -32
- package/dist/utils/get-utility-info.d.ts +2 -5
- package/dist/utils/get-utility-info.mjs +4 -16
- package/dist/utils/get-value-completion-items.d.ts +3 -2
- package/dist/utils/get-value-completion-items.mjs +145 -123
- package/dist/utils/query-syntax-completions.d.ts +3 -2
- package/dist/utils/query-syntax-completions.mjs +25 -44
- package/package.json +1 -1
- package/dist/common.cjs +0 -57
- package/dist/core.cjs +0 -246
- package/dist/features/edit-syntax-colors.cjs +0 -19
- package/dist/features/inspect-syntax.cjs +0 -70
- package/dist/features/render-syntax-colors.cjs +0 -89
- package/dist/features/suggest-syntax.cjs +0 -20
- package/dist/index.cjs +0 -29
- package/dist/settings.cjs +0 -84
- package/dist/utils/beautify-css.cjs +0 -13
- package/dist/utils/convert-color-token.cjs +0 -60
- package/dist/utils/create-doc.cjs +0 -26
- package/dist/utils/css-data-provider.cjs +0 -9
- package/dist/utils/css-data-provider.d.ts +0 -3
- package/dist/utils/css-data-provider.mjs +0 -7
- package/dist/utils/find-matching-brackets.cjs +0 -29
- package/dist/utils/find-matching-brackets.d.ts +0 -1
- package/dist/utils/find-matching-brackets.mjs +0 -27
- package/dist/utils/get-color-completion-items.cjs +0 -29
- package/dist/utils/get-css-data-documentation.cjs +0 -88
- package/dist/utils/get-css-data-documentation.d.ts +0 -5
- package/dist/utils/get-css-data-documentation.mjs +0 -86
- package/dist/utils/get-main-completion-items.cjs +0 -106
- package/dist/utils/get-main-completion-items.d.ts +0 -3
- package/dist/utils/get-main-completion-items.mjs +0 -104
- package/dist/utils/get-position.cjs +0 -12
- package/dist/utils/get-pseudo-class-completion-items.cjs +0 -67
- package/dist/utils/get-pseudo-element-completion-items.cjs +0 -56
- package/dist/utils/get-query-completion-items.cjs +0 -92
- package/dist/utils/get-range.cjs +0 -23
- package/dist/utils/get-utility-info.cjs +0 -33
- package/dist/utils/get-value-completion-items.cjs +0 -183
- package/dist/utils/query-syntax-completions.cjs +0 -115
- package/dist/utils/regex.cjs +0 -5
- package/dist/utils/sort-completion-items.cjs +0 -13
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
import { CompletionItemKind } from 'vscode-languageserver-protocol';
|
|
2
2
|
import getPseudoClassCompletionItems from './get-pseudo-class-completion-items.mjs';
|
|
3
3
|
import getPseudoElementCompletionItems from './get-pseudo-element-completion-items.mjs';
|
|
4
|
-
import {
|
|
5
|
-
import
|
|
6
|
-
import getMainCompletionItems from './get-main-completion-items.mjs';
|
|
4
|
+
import { GROUP_TRIGGER_CHARACTER, AT_SIGN, SELECTOR_SIGNS, QUERY_COMPARISON_OPERATORS, QUERY_LOGICAL_OPERATORS, SELECTOR_TRIGGER_CHARACTERS, generateCSS, createDefaultCSS } from '@master/css-language';
|
|
5
|
+
import getClassCompletionItems from './get-class-completion-items.mjs';
|
|
7
6
|
import getValueCompletionItems from './get-value-completion-items.mjs';
|
|
8
7
|
import getQueryCompletionItems from './get-query-completion-items.mjs';
|
|
9
|
-
import
|
|
8
|
+
import createCSSMarkdownDocumentation from './create-css-markdown-documentation.mjs';
|
|
9
|
+
import { matchesIndexedName, createCompletionIndex } from './completion-index.mjs';
|
|
10
10
|
|
|
11
|
-
function querySyntaxCompletions(q = '', css =
|
|
11
|
+
function querySyntaxCompletions(q = '', css = createDefaultCSS(), completionIndex = createCompletionIndex(css)) {
|
|
12
12
|
const fields = q.split(' ');
|
|
13
13
|
let field = fields[fields.length - 1];
|
|
14
14
|
const triggerCharacter = q.charAt(q.length - 1);
|
|
15
15
|
const invoked = triggerCharacter === ' ' || field.length === 0;
|
|
16
16
|
if (invoked || field === GROUP_TRIGGER_CHARACTER || triggerCharacter === ';') {
|
|
17
|
-
return
|
|
17
|
+
return getClassCompletionItems(css, completionIndex);
|
|
18
18
|
}
|
|
19
19
|
const isGroup = field.startsWith(GROUP_TRIGGER_CHARACTER);
|
|
20
20
|
if (isGroup) {
|
|
@@ -25,42 +25,26 @@ function querySyntaxCompletions(q = '', css = createCSS()) {
|
|
|
25
25
|
field = field.slice(1);
|
|
26
26
|
}
|
|
27
27
|
}
|
|
28
|
-
|
|
29
|
-
|
|
28
|
+
if (field.startsWith(AT_SIGN) || field.startsWith('~')) {
|
|
29
|
+
return [];
|
|
30
|
+
}
|
|
31
|
+
const keyMatch = field.match(/^[^'":\s]+:/);
|
|
30
32
|
const atMatches = Array.from(field.matchAll(/@(?=(?:[^'"]|'[^']*'|"[^"]*")*$)/g));
|
|
31
33
|
const valueSeparatorMatch = field.match(/\|(?=(?:[^'"]|'[^']*'|"[^"]*")*$)/g);
|
|
32
34
|
const atInvoked = atMatches.findIndex(({ index })=>index !== 0) !== -1;
|
|
33
35
|
const firstColonIndex = keyMatch ? keyMatch[0].length - 1 : -1;
|
|
34
36
|
const selectorInvokedRegex = new RegExp(`[${SELECTOR_SIGNS.join('')}](?=(?:[^'"]|'[^']*'|"[^"]*")*$)`);
|
|
35
37
|
const key = keyMatch ? keyMatch[0].slice(0, firstColonIndex) : undefined;
|
|
36
|
-
const
|
|
37
|
-
const
|
|
38
|
-
const isStyle = !!componentNames.find((eachStyleName)=>new RegExp(`^${eachStyleName}(?:\\b|_)`).test(field));
|
|
39
|
-
const isUtility = !!utilityNames.find((eachUtilityName)=>new RegExp(`^${eachUtilityName}(?:\\b|_)`).test(field));
|
|
38
|
+
const isStyle = completionIndex.componentNames.some((eachStyleName)=>matchesIndexedName(field, eachStyleName));
|
|
39
|
+
const isUtility = completionIndex.utilityNames.some((eachUtilityName)=>matchesIndexedName(field, eachUtilityName));
|
|
40
40
|
// check by utilities and components
|
|
41
41
|
if (!isStyle && !isUtility) {
|
|
42
42
|
if (key === undefined && !valueSeparatorMatch) {
|
|
43
|
-
|
|
44
|
-
* The server capability sets '@' '~' as the trigger characters for at and adjacent selectors,
|
|
45
|
-
* but these two characters are also the prefix symbols of `animation` and `transition`,
|
|
46
|
-
* and should be filtered to prevent hints all completions items.
|
|
47
|
-
* @example class="@"
|
|
48
|
-
* @example class="~"
|
|
49
|
-
*/ if (field.startsWith(ANIMATION_SIGN) || field.startsWith(TRANSITION_SIGN)) {
|
|
50
|
-
return getMainCompletionItems(css).filter((completionItem)=>completionItem.label.startsWith(field)).map((completionItem)=>({
|
|
51
|
-
...completionItem,
|
|
52
|
-
label: completionItem.label.slice(1)
|
|
53
|
-
}));
|
|
54
|
-
}
|
|
55
|
-
return getMainCompletionItems(css);
|
|
43
|
+
return getClassCompletionItems(css, completionIndex);
|
|
56
44
|
}
|
|
57
45
|
if (!atInvoked && !selectorInvokedRegex.test(field.slice(firstColonIndex + 1))) {
|
|
58
|
-
if (
|
|
59
|
-
return getValueCompletionItems(css,
|
|
60
|
-
} else if (field.startsWith(TRANSITION_SIGN) && firstColonIndex === -1) {
|
|
61
|
-
return getValueCompletionItems(css, 'transition');
|
|
62
|
-
} else if (key && firstColonIndex !== -1) {
|
|
63
|
-
return getValueCompletionItems(css, key);
|
|
46
|
+
if (key && firstColonIndex !== -1) {
|
|
47
|
+
return getValueCompletionItems(css, key, field.slice(firstColonIndex + 1), completionIndex);
|
|
64
48
|
}
|
|
65
49
|
}
|
|
66
50
|
}
|
|
@@ -72,36 +56,33 @@ function querySyntaxCompletions(q = '', css = createCSS()) {
|
|
|
72
56
|
...QUERY_COMPARISON_OPERATORS,
|
|
73
57
|
...QUERY_LOGICAL_OPERATORS
|
|
74
58
|
].includes(triggerCharacter)) {
|
|
75
|
-
return getQueryCompletionItems(css, triggerCharacter, field);
|
|
59
|
+
return getQueryCompletionItems(css, triggerCharacter, field, completionIndex);
|
|
76
60
|
}
|
|
77
61
|
if (!atInvoked && SELECTOR_TRIGGER_CHARACTERS.includes(triggerCharacter)) {
|
|
78
|
-
const pseudoElementCompletionItems = getPseudoElementCompletionItems(css, field);
|
|
62
|
+
const pseudoElementCompletionItems = getPseudoElementCompletionItems(css, field, completionIndex);
|
|
79
63
|
if (field.endsWith('::')) {
|
|
80
64
|
/**
|
|
81
65
|
* Consider trigger characters and fix insertText.
|
|
82
|
-
* @incorrect class="text
|
|
83
|
-
* @correct class="text
|
|
66
|
+
* @incorrect class="text-center::" -> class="text-center::::after"
|
|
67
|
+
* @correct class="text-center::" -> class="text-center::after"
|
|
84
68
|
*/ pseudoElementCompletionItems.forEach((completionItem)=>completionItem.insertText = completionItem.label.slice(2));
|
|
85
69
|
return pseudoElementCompletionItems;
|
|
86
70
|
} else {
|
|
87
|
-
const completionItems = getPseudoClassCompletionItems(css, field);
|
|
71
|
+
const completionItems = getPseudoClassCompletionItems(css, field, completionIndex);
|
|
88
72
|
completionItems.push(...pseudoElementCompletionItems);
|
|
89
73
|
/**
|
|
90
74
|
* Consider trigger characters and fix insertText.
|
|
91
|
-
* @incorrect class="text
|
|
92
|
-
* @correct class="text
|
|
75
|
+
* @incorrect class="text-center:" -> class="text-center::active"
|
|
76
|
+
* @correct class="text-center:" -> class="text-center:active"
|
|
93
77
|
*/ if (triggerCharacter === ':') {
|
|
94
78
|
completionItems.forEach((completionItem)=>completionItem.insertText = completionItem.label.slice(1));
|
|
95
79
|
} else {
|
|
96
80
|
completionItems.push({
|
|
97
81
|
label: '.<class>',
|
|
98
82
|
insertText: '.',
|
|
99
|
-
documentation:
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
], css),
|
|
103
|
-
docs: '/guide/selectors'
|
|
104
|
-
}),
|
|
83
|
+
documentation: createCSSMarkdownDocumentation(generateCSS([
|
|
84
|
+
field + '.class'
|
|
85
|
+
], css)),
|
|
105
86
|
kind: CompletionItemKind.Class
|
|
106
87
|
});
|
|
107
88
|
}
|
package/package.json
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"name":"@master/css-language-service","type":"module","scripts":{"build":"techor build \"src/**/*.ts\"","dev":"pnpm build --watch","type-check":"tsc --noEmit","lint":"eslint","test":"vitest"},"description":"Master CSS Language Service","author":"Aoyue Design LLC.","license":"MIT","repository":{"type":"git","url":"https://github.com/master-co/css.git","directory":"packages/language-service"},"dependencies":{"@
|
|
1
|
+
{"name":"@master/css-language-service","type":"module","scripts":{"build":"techor build \"src/**/*.ts\" --formats esm","dev":"pnpm build --watch","type-check":"tsc --noEmit","lint":"eslint","test":"vitest"},"description":"Master CSS Language Service","author":"Aoyue Design LLC.","license":"MIT","repository":{"type":"git","url":"https://github.com/master-co/css.git","directory":"packages/language-service"},"dependencies":{"@master/css":"^2.0.0-rc.70","@master/css-engine":"^2.0.0-rc.70","@master/css-language":"^2.0.0-rc.70","@techor/extend":"^3.2.5","colorjs.io":"^0.6.1","js-beautify":"^1.15.4","minimatch":"^10.2.5","vscode-languageserver-protocol":"^3.18.0","vscode-languageserver-textdocument":"^1.0.12"},"devDependencies":{"@types/vscode":"^1.125.0","vscode-languageserver":"^10.0.0","@master/css-schema":"^2.0.0-rc.70"},"sideEffects":false,"main":"./dist/index.mjs","module":"./dist/index.mjs","jsnext:main":"./dist/index.mjs","esnext":"./dist/index.mjs","types":"./dist/index.d.ts","exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.mjs","default":"./dist/index.mjs"},"./common":{"types":"./dist/common.d.ts","import":"./dist/common.mjs","default":"./dist/common.mjs"}},"files":["dist"],"publishConfig":{"access":"public","provenance":true},"version":"2.0.0-rc.70"}
|
package/dist/common.cjs
DELETED
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
var vscodeLanguageserverProtocol = require('vscode-languageserver-protocol');
|
|
4
|
-
var css = require('@master/css');
|
|
5
|
-
|
|
6
|
-
const INVOKED_TRIGGER_CHARACTERS = [
|
|
7
|
-
'"',
|
|
8
|
-
' ',
|
|
9
|
-
'\''
|
|
10
|
-
];
|
|
11
|
-
const VALUE_TRIGGER_CHARACTERS = [
|
|
12
|
-
css.SEPARATOR_SIGN,
|
|
13
|
-
css.DELIMITER_SIGN
|
|
14
|
-
];
|
|
15
|
-
const SELECTOR_TRIGGER_CHARACTERS = css.SELECTOR_SIGNS;
|
|
16
|
-
const AT_TRIGGER_CHARACTER = css.AT_SIGN;
|
|
17
|
-
const QUERY_TRIGGER_CHARACTERS = [
|
|
18
|
-
...css.QUERY_COMPARISON_OPERATORS,
|
|
19
|
-
...css.QUERY_LOGICAL_OPERATORS
|
|
20
|
-
];
|
|
21
|
-
const GROUP_TRIGGER_CHARACTER = '{';
|
|
22
|
-
const DECLARATION_SEPARATOR_TRIGGER_CHARACTER = ';';
|
|
23
|
-
const SERVER_CAPABILITIES = {
|
|
24
|
-
textDocumentSync: vscodeLanguageserverProtocol.TextDocumentSyncKind.Incremental,
|
|
25
|
-
// Tell the client that this server supports code completion.
|
|
26
|
-
completionProvider: {
|
|
27
|
-
resolveProvider: false,
|
|
28
|
-
workDoneProgress: false,
|
|
29
|
-
triggerCharacters: [
|
|
30
|
-
...new Set([
|
|
31
|
-
...INVOKED_TRIGGER_CHARACTERS,
|
|
32
|
-
...VALUE_TRIGGER_CHARACTERS,
|
|
33
|
-
...SELECTOR_TRIGGER_CHARACTERS,
|
|
34
|
-
...QUERY_TRIGGER_CHARACTERS,
|
|
35
|
-
DECLARATION_SEPARATOR_TRIGGER_CHARACTER,
|
|
36
|
-
AT_TRIGGER_CHARACTER,
|
|
37
|
-
GROUP_TRIGGER_CHARACTER
|
|
38
|
-
])
|
|
39
|
-
]
|
|
40
|
-
},
|
|
41
|
-
colorProvider: true,
|
|
42
|
-
hoverProvider: true,
|
|
43
|
-
workspace: {
|
|
44
|
-
workspaceFolders: {
|
|
45
|
-
supported: true
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
};
|
|
49
|
-
|
|
50
|
-
exports.AT_TRIGGER_CHARACTER = AT_TRIGGER_CHARACTER;
|
|
51
|
-
exports.DECLARATION_SEPARATOR_TRIGGER_CHARACTER = DECLARATION_SEPARATOR_TRIGGER_CHARACTER;
|
|
52
|
-
exports.GROUP_TRIGGER_CHARACTER = GROUP_TRIGGER_CHARACTER;
|
|
53
|
-
exports.INVOKED_TRIGGER_CHARACTERS = INVOKED_TRIGGER_CHARACTERS;
|
|
54
|
-
exports.QUERY_TRIGGER_CHARACTERS = QUERY_TRIGGER_CHARACTERS;
|
|
55
|
-
exports.SELECTOR_TRIGGER_CHARACTERS = SELECTOR_TRIGGER_CHARACTERS;
|
|
56
|
-
exports.SERVER_CAPABILITIES = SERVER_CAPABILITIES;
|
|
57
|
-
exports.VALUE_TRIGGER_CHARACTERS = VALUE_TRIGGER_CHARACTERS;
|
package/dist/core.cjs
DELETED
|
@@ -1,246 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
var css = require('@master/css');
|
|
4
|
-
var extend = require('@techor/extend');
|
|
5
|
-
var EventEmitter = require('node:events');
|
|
6
|
-
var settings = require('./settings.cjs');
|
|
7
|
-
var minimatch = require('minimatch');
|
|
8
|
-
var inspectSyntax = require('./features/inspect-syntax.cjs');
|
|
9
|
-
var renderSyntaxColors = require('./features/render-syntax-colors.cjs');
|
|
10
|
-
var editSyntaxColors = require('./features/edit-syntax-colors.cjs');
|
|
11
|
-
var suggestSyntax = require('./features/suggest-syntax.cjs');
|
|
12
|
-
var findMatchingBrackets = require('./utils/find-matching-brackets.cjs');
|
|
13
|
-
var escapeRegexp = require('lodash.escaperegexp');
|
|
14
|
-
|
|
15
|
-
class CSSLanguageService extends EventEmitter {
|
|
16
|
-
customSettings;
|
|
17
|
-
css;
|
|
18
|
-
settings;
|
|
19
|
-
constructor(customSettings){
|
|
20
|
-
super(), this.customSettings = customSettings;
|
|
21
|
-
this.settings = extend(settings, customSettings);
|
|
22
|
-
this.css = css.createCSS(this.settings.config);
|
|
23
|
-
}
|
|
24
|
-
inspectSyntax(...params) {
|
|
25
|
-
if (this.settings.inspectSyntax && this.isDocumentAccepted(params[0])) return inspectSyntax?.call(this, ...params);
|
|
26
|
-
}
|
|
27
|
-
renderSyntaxColors(...params) {
|
|
28
|
-
if (this.settings.renderSyntaxColors && this.isDocumentAccepted(params[0])) return renderSyntaxColors?.call(this, ...params);
|
|
29
|
-
}
|
|
30
|
-
editSyntaxColors(...params) {
|
|
31
|
-
if (this.settings.editSyntaxColors && this.isDocumentAccepted(params[0])) return editSyntaxColors?.call(this, ...params);
|
|
32
|
-
}
|
|
33
|
-
suggestSyntax(...params) {
|
|
34
|
-
if (this.settings.suggestSyntax && this.isDocumentAccepted(params[0])) return suggestSyntax?.call(this, ...params);
|
|
35
|
-
}
|
|
36
|
-
getClassPosition(textDocument, position) {
|
|
37
|
-
const positionIndex = textDocument.offsetAt(position);
|
|
38
|
-
const startIndex = textDocument.offsetAt({
|
|
39
|
-
line: position.line - 100,
|
|
40
|
-
character: 0
|
|
41
|
-
}) ?? 0;
|
|
42
|
-
const endIndex = textDocument.offsetAt({
|
|
43
|
-
line: position.line + 100,
|
|
44
|
-
character: 0
|
|
45
|
-
}) ?? undefined;
|
|
46
|
-
const text = textDocument.getText().substring(startIndex, endIndex);
|
|
47
|
-
const { classAttributeBindings, classAttributes, classDeclarations, classFunctions } = this.settings;
|
|
48
|
-
const normalizeClassNamePosition = (className, attrStart, escapeCharacter)=>{
|
|
49
|
-
/**
|
|
50
|
-
* Matching classes, including empty string after white space
|
|
51
|
-
* @example <div class="class-a class-b "></div>
|
|
52
|
-
* @url https://regex101.com/r/LnBLAV/1
|
|
53
|
-
*/ for (const eachClassMatch of className.matchAll(/(?:[^\s]+)?/g)){
|
|
54
|
-
if (eachClassMatch.index === undefined) continue;
|
|
55
|
-
const raw = eachClassMatch[0];
|
|
56
|
-
const classStartIndex = attrStart + eachClassMatch.index;
|
|
57
|
-
const classEndIndex = classStartIndex + raw.length;
|
|
58
|
-
if (classStartIndex <= positionIndex - startIndex && positionIndex - startIndex <= classEndIndex) {
|
|
59
|
-
return {
|
|
60
|
-
range: {
|
|
61
|
-
start: classStartIndex,
|
|
62
|
-
end: startIndex + classEndIndex
|
|
63
|
-
},
|
|
64
|
-
raw,
|
|
65
|
-
token: raw.replace(new RegExp('\\' + escapeCharacter, 'g'), escapeCharacter)
|
|
66
|
-
};
|
|
67
|
-
} else if (attrStart === classEndIndex) {
|
|
68
|
-
return {
|
|
69
|
-
range: {
|
|
70
|
-
start: attrStart,
|
|
71
|
-
end: attrStart
|
|
72
|
-
},
|
|
73
|
-
raw: '',
|
|
74
|
-
token: ''
|
|
75
|
-
};
|
|
76
|
-
}
|
|
77
|
-
}
|
|
78
|
-
};
|
|
79
|
-
const resolve = (classMatchers, handle)=>{
|
|
80
|
-
for (const eachClassMatcher of classMatchers){
|
|
81
|
-
let [eachPattern, start, end] = eachClassMatcher;
|
|
82
|
-
end = end ?? start;
|
|
83
|
-
for (const eachClassPostioinMatch of text.matchAll(new RegExp(`(?:\\s|\\.)${eachPattern}${escapeRegexp(start)}`, 'g'))){
|
|
84
|
-
if (eachClassPostioinMatch.index === undefined) continue;
|
|
85
|
-
const eachClassAttributeString = eachClassPostioinMatch[0];
|
|
86
|
-
const eachAttrStart = eachClassPostioinMatch.index + eachClassAttributeString.length;
|
|
87
|
-
const eachClassPositionEnd = findMatchingBrackets(text, eachAttrStart, start, end);
|
|
88
|
-
if (!eachClassPositionEnd) continue;
|
|
89
|
-
if ((eachAttrStart <= positionIndex - startIndex && eachClassPositionEnd >= positionIndex - startIndex) === true) {
|
|
90
|
-
const classPosition = handle(eachAttrStart, eachClassPositionEnd, eachClassMatcher);
|
|
91
|
-
if (classPosition) return classPosition;
|
|
92
|
-
} else if (eachClassPostioinMatch.index > positionIndex - startIndex) {
|
|
93
|
-
break;
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
};
|
|
98
|
-
const stringExpressions = [];
|
|
99
|
-
const assignmentExpressions = [];
|
|
100
|
-
classAttributes?.forEach((eachClassAttribute)=>{
|
|
101
|
-
stringExpressions.push([
|
|
102
|
-
eachClassAttribute + '=',
|
|
103
|
-
'"',
|
|
104
|
-
'"'
|
|
105
|
-
], [
|
|
106
|
-
eachClassAttribute + '=',
|
|
107
|
-
'\'',
|
|
108
|
-
'\''
|
|
109
|
-
]);
|
|
110
|
-
});
|
|
111
|
-
classDeclarations?.forEach((eachClassDeclaration)=>{
|
|
112
|
-
stringExpressions.push([
|
|
113
|
-
eachClassDeclaration + '(?:\\s+)?(?::|=)(?:\\s+)?',
|
|
114
|
-
'"',
|
|
115
|
-
'"'
|
|
116
|
-
], [
|
|
117
|
-
eachClassDeclaration + '(?:\\s+)?(?::|=)(?:\\s+)?',
|
|
118
|
-
'`',
|
|
119
|
-
'`'
|
|
120
|
-
], [
|
|
121
|
-
eachClassDeclaration + '(?:\\s+)?(?::|=)(?:\\s+)?',
|
|
122
|
-
'\'',
|
|
123
|
-
'\''
|
|
124
|
-
]);
|
|
125
|
-
assignmentExpressions.push([
|
|
126
|
-
eachClassDeclaration + '(?:\\s+)?(?::|=)(?:\\s+)?',
|
|
127
|
-
'{',
|
|
128
|
-
'}'
|
|
129
|
-
]);
|
|
130
|
-
});
|
|
131
|
-
classFunctions?.forEach((eachClassFunction)=>{
|
|
132
|
-
/**
|
|
133
|
-
* @example clsx`class-a class-b`
|
|
134
|
-
*/ stringExpressions.push([
|
|
135
|
-
eachClassFunction,
|
|
136
|
-
'`',
|
|
137
|
-
'`'
|
|
138
|
-
]);
|
|
139
|
-
/**
|
|
140
|
-
* @example clsx('class-a class-b')
|
|
141
|
-
*/ assignmentExpressions.push([
|
|
142
|
-
eachClassFunction,
|
|
143
|
-
'(',
|
|
144
|
-
')'
|
|
145
|
-
]);
|
|
146
|
-
});
|
|
147
|
-
/**
|
|
148
|
-
* @example <div class=""></div>
|
|
149
|
-
* */ if (stringExpressions?.length) {
|
|
150
|
-
const classPosition = resolve(stringExpressions, (eachAttrStart, eachClassPositionEnd, [eachPattern, pair])=>{
|
|
151
|
-
const eachClassName = text.substring(eachAttrStart, eachClassPositionEnd);
|
|
152
|
-
/**
|
|
153
|
-
* @example <div class=""></div>
|
|
154
|
-
*/ if (eachClassName === undefined) {
|
|
155
|
-
return {
|
|
156
|
-
range: {
|
|
157
|
-
start: eachAttrStart,
|
|
158
|
-
end: eachAttrStart
|
|
159
|
-
},
|
|
160
|
-
token: '',
|
|
161
|
-
raw: ''
|
|
162
|
-
};
|
|
163
|
-
}
|
|
164
|
-
const classNameStart = eachAttrStart;
|
|
165
|
-
const classPosition = normalizeClassNamePosition(eachClassName, classNameStart, pair);
|
|
166
|
-
if (classPosition) return classPosition;
|
|
167
|
-
});
|
|
168
|
-
if (classPosition) return classPosition;
|
|
169
|
-
}
|
|
170
|
-
if (classAttributeBindings) {
|
|
171
|
-
for(const eachClassAttribute in classAttributeBindings){
|
|
172
|
-
const eachClassAttributeBinding = classAttributeBindings[eachClassAttribute];
|
|
173
|
-
if (eachClassAttributeBinding === false) continue;
|
|
174
|
-
assignmentExpressions.push([
|
|
175
|
-
eachClassAttribute + '=',
|
|
176
|
-
eachClassAttributeBinding[0],
|
|
177
|
-
eachClassAttributeBinding[1]
|
|
178
|
-
]);
|
|
179
|
-
}
|
|
180
|
-
}
|
|
181
|
-
/**
|
|
182
|
-
* attribute binding
|
|
183
|
-
* @example <div className={''}></div>
|
|
184
|
-
* @example <div :class="isActive ? 'block' : 'hidden'"></div>
|
|
185
|
-
* */ if (assignmentExpressions?.length) {
|
|
186
|
-
const classPosition = resolve(assignmentExpressions, (eachAttrStart, eachClassPositionEnd, eachClassMatcher)=>{
|
|
187
|
-
const eachClassPositionExpression = text.substring(eachAttrStart, eachClassPositionEnd);
|
|
188
|
-
/**
|
|
189
|
-
* @example <div className={""}></div>
|
|
190
|
-
*/ if ([
|
|
191
|
-
'""',
|
|
192
|
-
'\'\'',
|
|
193
|
-
'``'
|
|
194
|
-
].includes(eachClassPositionExpression)) {
|
|
195
|
-
return {
|
|
196
|
-
range: {
|
|
197
|
-
start: eachAttrStart + 1,
|
|
198
|
-
end: eachAttrStart + 1
|
|
199
|
-
},
|
|
200
|
-
raw: '',
|
|
201
|
-
token: ''
|
|
202
|
-
};
|
|
203
|
-
}
|
|
204
|
-
// 1. "
|
|
205
|
-
for (const classExpressionMatch of eachClassPositionExpression.matchAll(/(?<!\\)"([\s\S]*?)(?<!\\)"/g)){
|
|
206
|
-
if (classExpressionMatch.index === undefined) continue;
|
|
207
|
-
const eachClassName = classExpressionMatch[1];
|
|
208
|
-
const classNameStart = eachAttrStart + classExpressionMatch.index + 1 // " length
|
|
209
|
-
;
|
|
210
|
-
const classPosition = normalizeClassNamePosition(eachClassName, classNameStart, '"');
|
|
211
|
-
if (classPosition) return classPosition;
|
|
212
|
-
}
|
|
213
|
-
// 2. '
|
|
214
|
-
for (const classExpressionMatch of eachClassPositionExpression.matchAll(/(?<!\\)'([\s\S]*?)(?<!\\)'/g)){
|
|
215
|
-
if (classExpressionMatch.index === undefined) continue;
|
|
216
|
-
const eachClassName = classExpressionMatch[1];
|
|
217
|
-
const classNameStart = eachAttrStart + classExpressionMatch.index + 1 // ' length
|
|
218
|
-
;
|
|
219
|
-
const classPosition = normalizeClassNamePosition(eachClassName, classNameStart, '\'');
|
|
220
|
-
if (classPosition) return classPosition;
|
|
221
|
-
}
|
|
222
|
-
// 3. `
|
|
223
|
-
for (const classExpressionMatch of eachClassPositionExpression.matchAll(/(?<!\\)`([\s\S]*?)(?<!\\)`/g)){
|
|
224
|
-
if (classExpressionMatch.index === undefined) continue;
|
|
225
|
-
const eachClassName = classExpressionMatch[1];
|
|
226
|
-
const classNameStart = eachAttrStart + classExpressionMatch.index + 1 // ` length
|
|
227
|
-
;
|
|
228
|
-
const classPosition = normalizeClassNamePosition(eachClassName, classNameStart, '`');
|
|
229
|
-
if (classPosition) return classPosition;
|
|
230
|
-
}
|
|
231
|
-
});
|
|
232
|
-
if (classPosition) return classPosition;
|
|
233
|
-
}
|
|
234
|
-
}
|
|
235
|
-
isDocumentAccepted(doc) {
|
|
236
|
-
if (!this.settings.exclude) return true;
|
|
237
|
-
for (const exclude of this.settings.exclude){
|
|
238
|
-
if (minimatch.minimatch(doc.uri, exclude)) {
|
|
239
|
-
return false;
|
|
240
|
-
}
|
|
241
|
-
}
|
|
242
|
-
return true;
|
|
243
|
-
}
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
module.exports = CSSLanguageService;
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
var convertColorToken = require('../utils/convert-color-token.cjs');
|
|
4
|
-
|
|
5
|
-
function editSyntaxColors(document, color, range) {
|
|
6
|
-
const colorPresentations = [];
|
|
7
|
-
const selectedColorToken = document.getText(range);
|
|
8
|
-
const targetColorToken = convertColorToken.default(color, selectedColorToken, this.css);
|
|
9
|
-
if (targetColorToken) colorPresentations.push({
|
|
10
|
-
label: targetColorToken,
|
|
11
|
-
textEdit: {
|
|
12
|
-
range,
|
|
13
|
-
newText: targetColorToken
|
|
14
|
-
}
|
|
15
|
-
});
|
|
16
|
-
return colorPresentations;
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
module.exports = editSyntaxColors;
|
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
var getCssDataDocumentation = require('../utils/get-css-data-documentation.cjs');
|
|
4
|
-
var css = require('@master/css');
|
|
5
|
-
var cssDataProvider = require('../utils/css-data-provider.cjs');
|
|
6
|
-
var getUtilityInfo = require('../utils/get-utility-info.cjs');
|
|
7
|
-
|
|
8
|
-
function inspectSyntax(document, position) {
|
|
9
|
-
const classPosition = this.getClassPosition(document, position);
|
|
10
|
-
if (!classPosition) return;
|
|
11
|
-
const { token } = classPosition;
|
|
12
|
-
const range = {
|
|
13
|
-
start: document.positionAt(classPosition.range.start),
|
|
14
|
-
end: document.positionAt(classPosition.range.end)
|
|
15
|
-
};
|
|
16
|
-
const componentClasses = this.css.components.get(token);
|
|
17
|
-
if (componentClasses) {
|
|
18
|
-
const documentation = getCssDataDocumentation.getCSSDataDocumentation({}, {
|
|
19
|
-
generatedCSS: css.generateCSS([
|
|
20
|
-
token
|
|
21
|
-
], this.css),
|
|
22
|
-
docs: '/guide/components'
|
|
23
|
-
});
|
|
24
|
-
if (documentation) {
|
|
25
|
-
return {
|
|
26
|
-
contents: {
|
|
27
|
-
kind: documentation.kind,
|
|
28
|
-
value: `(style) ` + componentClasses.join(' ') + '\n' + documentation.value
|
|
29
|
-
}
|
|
30
|
-
};
|
|
31
|
-
}
|
|
32
|
-
} else {
|
|
33
|
-
const rules = this.css.generate(token);
|
|
34
|
-
const rule = rules[0];
|
|
35
|
-
if (rule) {
|
|
36
|
-
if (rule.type === css.SyntaxRuleType.Utility) {
|
|
37
|
-
const { data, docs } = getUtilityInfo(rule.registeredSyntax, this.css);
|
|
38
|
-
const documentation = getCssDataDocumentation.getCSSDataDocumentation(data, {
|
|
39
|
-
generatedCSS: css.generateCSS([
|
|
40
|
-
token
|
|
41
|
-
], this.css),
|
|
42
|
-
docs
|
|
43
|
-
});
|
|
44
|
-
if (documentation) {
|
|
45
|
-
return {
|
|
46
|
-
contents: documentation,
|
|
47
|
-
range
|
|
48
|
-
};
|
|
49
|
-
}
|
|
50
|
-
} else {
|
|
51
|
-
const nativeProperties = cssDataProvider.provideProperties();
|
|
52
|
-
const nativeCSSPropertyData = nativeProperties.find(({ name })=>name === rule.id);
|
|
53
|
-
const documentation = getCssDataDocumentation.getCSSDataDocumentation(nativeCSSPropertyData, {
|
|
54
|
-
generatedCSS: css.generateCSS([
|
|
55
|
-
token
|
|
56
|
-
], this.css),
|
|
57
|
-
docs: '/reference/' + (css.isCoreRule(rule.id) && rule.id)
|
|
58
|
-
});
|
|
59
|
-
if (documentation) {
|
|
60
|
-
return {
|
|
61
|
-
contents: documentation,
|
|
62
|
-
range
|
|
63
|
-
};
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
module.exports = inspectSyntax;
|
|
@@ -1,89 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
var regex = require('../utils/regex.cjs');
|
|
4
|
-
var Color = require('colorjs.io');
|
|
5
|
-
var css = require('@master/css');
|
|
6
|
-
|
|
7
|
-
async function renderSyntaxColors(document) {
|
|
8
|
-
const text = document.getText() ?? '';
|
|
9
|
-
const colorInformations = [];
|
|
10
|
-
try {
|
|
11
|
-
for (const instanceMatch of text.matchAll(regex.instancePattern)){
|
|
12
|
-
if (instanceMatch.index === undefined) break;
|
|
13
|
-
const instanceStartIndex = instanceMatch.index;
|
|
14
|
-
const syntax = instanceMatch[0];
|
|
15
|
-
const rule = this.css.generate(syntax)[0];
|
|
16
|
-
if (rule && rule.type !== css.SyntaxRuleType.Utility) {
|
|
17
|
-
const keyTokenLength = rule.keyToken?.length ?? 0;
|
|
18
|
-
let currentLength = 0;
|
|
19
|
-
const resolveValueComponent = (valueComponent)=>{
|
|
20
|
-
if (valueComponent.text === undefined) return; // text is always existing, just for type
|
|
21
|
-
const startOffset = instanceStartIndex + keyTokenLength + currentLength;
|
|
22
|
-
// TODO: check number mt:30
|
|
23
|
-
const valueComponentTokenLength = valueComponent.token.length;
|
|
24
|
-
let color;
|
|
25
|
-
switch(valueComponent.type){
|
|
26
|
-
case 'function':
|
|
27
|
-
if ([
|
|
28
|
-
'rgb',
|
|
29
|
-
'rgba',
|
|
30
|
-
'hsl',
|
|
31
|
-
'hsla',
|
|
32
|
-
'hwb',
|
|
33
|
-
'lab',
|
|
34
|
-
'lch',
|
|
35
|
-
'oklab',
|
|
36
|
-
'oklch',
|
|
37
|
-
'color'
|
|
38
|
-
].includes(valueComponent.name)) {
|
|
39
|
-
color = new Color(valueComponent.text);
|
|
40
|
-
} else if (valueComponent.children.length) {
|
|
41
|
-
currentLength += valueComponent.name.length + 1; // function name + '('
|
|
42
|
-
valueComponent.children.forEach(resolveValueComponent);
|
|
43
|
-
}
|
|
44
|
-
break;
|
|
45
|
-
case 'variable':
|
|
46
|
-
if (valueComponent.variable?.type === 'color') {
|
|
47
|
-
color = new Color(valueComponent.text);
|
|
48
|
-
}
|
|
49
|
-
break;
|
|
50
|
-
case 'string':
|
|
51
|
-
if (valueComponent.text !== '#' && valueComponent.text?.startsWith('#')) {
|
|
52
|
-
color = new Color(valueComponent.text);
|
|
53
|
-
}
|
|
54
|
-
break;
|
|
55
|
-
}
|
|
56
|
-
// check if rgba is valid
|
|
57
|
-
if (color) {
|
|
58
|
-
const rgbaColor = color.to('srgb');
|
|
59
|
-
colorInformations.push({
|
|
60
|
-
range: {
|
|
61
|
-
start: document.positionAt(startOffset),
|
|
62
|
-
end: document.positionAt(startOffset + valueComponentTokenLength)
|
|
63
|
-
},
|
|
64
|
-
color: {
|
|
65
|
-
red: rgbaColor.r,
|
|
66
|
-
green: rgbaColor.g,
|
|
67
|
-
blue: rgbaColor.b,
|
|
68
|
-
alpha: Number(rgbaColor.alpha)
|
|
69
|
-
}
|
|
70
|
-
});
|
|
71
|
-
}
|
|
72
|
-
currentLength += valueComponentTokenLength || 0;
|
|
73
|
-
};
|
|
74
|
-
rule.valueComponents.forEach(resolveValueComponent);
|
|
75
|
-
}
|
|
76
|
-
}
|
|
77
|
-
} catch (e) {}
|
|
78
|
-
const colorIndexSet = new Set();
|
|
79
|
-
return colorInformations.filter((item)=>{
|
|
80
|
-
if (colorIndexSet.has(item.range.start)) {
|
|
81
|
-
return false;
|
|
82
|
-
} else {
|
|
83
|
-
colorIndexSet.add(item.range.start);
|
|
84
|
-
return true;
|
|
85
|
-
}
|
|
86
|
-
});
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
module.exports = renderSyntaxColors;
|
|
@@ -1,20 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
var querySyntaxCompletions = require('../utils/query-syntax-completions.cjs');
|
|
4
|
-
|
|
5
|
-
function suggestSyntax(document, position, context) {
|
|
6
|
-
const classPosition = this.getClassPosition(document, position);
|
|
7
|
-
if (classPosition !== undefined) {
|
|
8
|
-
const q = context?.triggerCharacter === ' ' ? '' : document.getText({
|
|
9
|
-
start: document.positionAt(classPosition.range.start),
|
|
10
|
-
end: position
|
|
11
|
-
});
|
|
12
|
-
return querySyntaxCompletions(q, this.css);
|
|
13
|
-
}
|
|
14
|
-
// todo
|
|
15
|
-
// else if (isInstance === true && checkConfigColorsBlock(document, position) === true) {
|
|
16
|
-
// return getColorCompletionItems(this.css)
|
|
17
|
-
// }
|
|
18
|
-
}
|
|
19
|
-
|
|
20
|
-
module.exports = suggestSyntax;
|