@master/css-language-server 2.0.0-beta.75 → 2.0.0-beta.77

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.
@@ -1,296 +0,0 @@
1
- import {
2
- TextDocuments,
3
- ColorInformation,
4
- Color,
5
- DocumentColorParams,
6
- Position,
7
- ColorPresentationParams,
8
- ColorPresentation,
9
- TextEdit
10
- } from 'vscode-languageserver/node'
11
- import { TextDocument } from 'vscode-languageserver-textdocument'
12
-
13
- import MasterCSS from '@master/css'
14
- import { hexToRgb } from './utils/hex-to-rgb'
15
- import { instancePattern } from './utils/regex'
16
-
17
-
18
- export async function GetColorRender(DocumentColor: DocumentColorParams, documents: TextDocuments<TextDocument>): Promise<ColorInformation[]> {
19
- const colors: ColorInformation[] = []
20
- const documentUri = DocumentColor.textDocument.uri
21
- const document = documents.get(documentUri)
22
- const text = document?.getText() ?? ''
23
-
24
- if (typeof document == undefined) {
25
- return []
26
- }
27
- let classMatch: RegExpExecArray | null
28
- const hexColorPattern = /(:\s*)'#([0-9a-fA-F]{6,8})'/g
29
- let colorMatch: RegExpExecArray | null
30
-
31
- const classPattern = new RegExp('(?<=colors:\\s*{\\s*.*)([^}]*)}','g')
32
- while ((classMatch = classPattern.exec(text)) !== null) {
33
- //#region for rgb、hls
34
- while ((colorMatch = hexColorPattern.exec(classMatch[0]))) {
35
- const colorInformation: ColorInformation = {
36
- range: {
37
- start: document?.positionAt(classMatch.index + colorMatch.index + colorMatch[1].length ) ?? Position.create(0, 0),
38
- end: document?.positionAt(classMatch.index + colorMatch.index + colorMatch[0].length -1) ?? Position.create(0, 0)
39
- },
40
- color: getColorValue(hexToRgb(colorMatch[2]))
41
- }
42
- colors.push(colorInformation)
43
- }
44
- //#endregion for rgb、hls
45
- }
46
- return colors
47
- }
48
-
49
- export async function GetDocumentColors(DocumentColor: DocumentColorParams, documents: TextDocuments<TextDocument>, classAttributes: string[], masterCss: MasterCSS = new MasterCSS()
50
- ): Promise<ColorInformation[]> {
51
- let colors: ColorInformation[] = []
52
-
53
- const documentUri = DocumentColor.textDocument.uri
54
- const document = documents.get(documentUri)
55
- const text = document?.getText() ?? ''
56
-
57
- if (typeof document == undefined) {
58
- return []
59
- }
60
-
61
- const allMasterCssColorKeys = Object.keys(masterCss.colorsThemesMap)
62
-
63
- let instanceMatch: RegExpExecArray | null
64
- while ((instanceMatch = instancePattern.exec(text)) !== null) {
65
- const instanceStartIndex = instanceMatch.index
66
- const theme = masterCss.themeNames.find(x => instanceMatch?.[0]?.endsWith(`@${x}`)) ?? ''
67
-
68
- const colorPattern = /(?<=[:;|])(?:#?\w+(?:-[\d]{1,2})?(?:\/.?[\d]*)?(?:\([^\s)]+\))?)/g
69
- const rgbaColorPattern = /rgba?\(([\d.]+),([\d.]+),([\d.]+)(?:,([\d.]+))?\)/g
70
- const hslaColorPattern = /hsla?\(([\d.]+),([\d.]+)%,([\d.]+)%(?:,([\d.]+))?\)/g
71
- const hexColorPattern = /#([0-9a-fA-F]{6,8})/g
72
- let colorMatch: RegExpExecArray | null
73
- let colorMatch2: RegExpExecArray | null
74
- let colorName: string
75
- let colorNumber: number
76
- let colorAlpha: number
77
- //check color
78
- while ((colorMatch = colorPattern.exec(instanceMatch[0])) !== null) {
79
- //#region for rgb、hls
80
- if ((colorMatch2 = rgbaColorPattern.exec(colorMatch[0]))) {
81
- const colorInformation: ColorInformation = {
82
- range: {
83
- start: document?.positionAt(instanceStartIndex + colorMatch.index) ?? Position.create(0, 0),
84
- end: document?.positionAt(instanceStartIndex + colorMatch.index + colorMatch[0].length) ?? Position.create(0, 0)
85
- },
86
- color: getColorValue({ red: Number(colorMatch2[1]), green: Number(colorMatch2[2]), blue: Number(colorMatch2[3]), alpha: colorMatch2[4] == undefined ? 1 : Number(colorMatch2[4]) })
87
- }
88
- colors.push(colorInformation)
89
- }
90
- else if ((colorMatch2 = hslaColorPattern.exec(colorMatch[0]))) {
91
- const colorInformation: ColorInformation = {
92
- range: {
93
- start: document?.positionAt(instanceStartIndex + colorMatch.index) ?? Position.create(0, 0),
94
- end: document?.positionAt(instanceStartIndex + colorMatch.index + colorMatch[0].length) ?? Position.create(0, 0)
95
- },
96
- color: getColorValue(hslToRgb(Number(colorMatch2[1]), Number(colorMatch2[2]), Number(colorMatch2[3]), colorMatch2[4] == undefined ? 1 : Number(colorMatch2[4])))
97
- }
98
- colors.push(colorInformation)
99
- }
100
- else if ((colorMatch2 = hexColorPattern.exec(colorMatch[0]))) {
101
- const colorInformation: ColorInformation = {
102
- range: {
103
- start: document?.positionAt(instanceStartIndex + colorMatch.index) ?? Position.create(0, 0),
104
- end: document?.positionAt(instanceStartIndex + colorMatch.index + colorMatch[0].length) ?? Position.create(0, 0)
105
- },
106
- color: getColorValue(hexToRgb(colorMatch2[1]))
107
- }
108
- colors.push(colorInformation)
109
- }
110
- //#endregion for rgb、hls
111
-
112
- //#region for mastercss color
113
- colorAlpha = 1
114
- if (colorMatch[0].split('/').length == 2) {
115
- colorAlpha = Number('0' + colorMatch[0].split('/')[1])
116
- }
117
- if (colorMatch[0].split('-').length == 1)//:black black/.5
118
- {
119
- colorName = colorMatch[0].split('/')[0]
120
- colorName = colorName.endsWith('_') ? colorName.replace('_', '') : colorName
121
- if (allMasterCssColorKeys.find(x => x == colorName)) {
122
- const colorInformation: ColorInformation = {
123
- range: {
124
- start: document?.positionAt(instanceStartIndex + colorMatch.index) ?? Position.create(0, 0),
125
- end: document?.positionAt(instanceStartIndex + colorMatch.index + colorMatch[0].length) ?? Position.create(0, 0)
126
- },
127
- color: getColorsRGBA(colorName, '', colorAlpha, theme, masterCss)
128
- }
129
- colors.push(colorInformation)
130
- }
131
-
132
- }
133
- else if (colorMatch[0].split('-').length == 2) { //:red-60 red-60/.5
134
-
135
- colorName = colorMatch[0].split('-')[0]
136
- colorNumber = Number(colorMatch[0].split('-')[1].split('/')[0])
137
-
138
-
139
- if (allMasterCssColorKeys.find(x => x == colorName) && colorNumber > 0 && colorNumber < 100) {
140
- const colorInformation: ColorInformation = {
141
- range: {
142
- start: document?.positionAt(instanceStartIndex + colorMatch.index) ?? Position.create(0, 0),
143
- end: document?.positionAt(instanceStartIndex + colorMatch.index + colorMatch[0].length) ?? Position.create(0, 0)
144
- },
145
- color: getColorsRGBA(colorName, colorNumber, colorAlpha, theme, masterCss)
146
- }
147
- colors.push(colorInformation)
148
- }
149
- }
150
-
151
- else if (colorMatch[0].split('-').length != 2) {
152
- continue
153
- }
154
- //#endregion for mastercss color
155
- }
156
- }
157
-
158
- const set = new Set()
159
- colors = colors.filter(item => {
160
- if (set.has(document?.offsetAt(item.range.start))) {
161
- return false
162
- } else {
163
- set.add(document?.offsetAt(item.range.start))
164
- return true
165
- }
166
- })
167
-
168
- return colors
169
- }
170
-
171
- function getColorsRGBA(colorName: string, colorNumber: number | string, colorAlpha = 1, theme = '', masterCss: MasterCSS = new MasterCSS()): Color {
172
- try {
173
- const colorNumberMap = masterCss.colorsThemesMap[colorName]
174
- const levelRgb = hexToRgb(colorNumberMap[colorNumber][theme] ?? colorNumberMap[colorNumber][''] ?? Object.values(colorNumberMap[colorNumber])[0])
175
-
176
- return { red: levelRgb.red/255, green: levelRgb.green/255, blue: levelRgb.blue/255, alpha: colorAlpha }
177
- } catch(ex) {
178
- return { red: 0, green: 0, blue: 0, alpha: 1 }
179
- }
180
- }
181
- export interface HWBA { h: number; w: number; b: number; a: number; }
182
-
183
- export interface HSLA { h: number; s: number; l: number; a: number; }
184
-
185
- function toTwoDigitHex(n: number): string {
186
- const r = n.toString(16)
187
- return r.length !== 2 ? '0' + r : r
188
- }
189
- export function hslFromColor(rgba: Color): HSLA {
190
- const r = rgba.red
191
- const g = rgba.green
192
- const b = rgba.blue
193
- const a = rgba.alpha
194
-
195
- const max = Math.max(r, g, b)
196
- const min = Math.min(r, g, b)
197
- let h = 0
198
- let s = 0
199
- const l = (min + max) / 2
200
- const chroma = max - min
201
-
202
- if (chroma > 0) {
203
- s = Math.min((l <= 0.5 ? chroma / (2 * l) : chroma / (2 - (2 * l))), 1)
204
-
205
- switch (max) {
206
- case r: h = (g - b) / chroma + (g < b ? 6 : 0); break
207
- case g: h = (b - r) / chroma + 2; break
208
- case b: h = (r - g) / chroma + 4; break
209
- }
210
-
211
- h *= 60
212
- h = Math.round(h)
213
- }
214
- return { h, s, l, a }
215
- }
216
- export function hwbFromColor(rgba: Color): HWBA {
217
- const hsl = hslFromColor(rgba)
218
- const white = Math.min(rgba.red, rgba.green, rgba.blue)
219
- const black = 1 - Math.max(rgba.red, rgba.green, rgba.blue)
220
-
221
- return {
222
- h: hsl.h,
223
- w: white,
224
- b: black,
225
- a: hsl.a
226
- }
227
- }
228
-
229
-
230
- export function hslToRgb(h: number, s: number, l: number, alpha?: number): Color {
231
- l /= 100
232
- const k = (n: number) => (n + h / 30) % 12
233
- const a = (s / 100) * Math.min(l, 1 - l)
234
- const f = (n: number) =>
235
- l - a * Math.max(-1, Math.min(k(n) - 3, Math.min(9 - k(n), 1)))
236
-
237
- return { red: 255 * f(0), green: 255 * f(8), blue: 255 * f(4), alpha: alpha ?? 1 }
238
- }
239
-
240
- export function getColorValue(color: Color): Color {
241
- return { red: color.red / 255.0, green: color.green / 255.0, blue: color.blue / 255.0, alpha: color.alpha }
242
- }
243
-
244
- export function GetColorPresentation(params: ColorPresentationParams, isColorRender = false) {
245
- const result: ColorPresentation[] = []
246
- const color = params.color
247
- const range = params.range
248
-
249
-
250
- const red256 = Math.round(color.red * 255), green256 = Math.round(color.green * 255), blue256 = Math.round(color.blue * 255)
251
-
252
- let label
253
-
254
- if(isColorRender)
255
- {
256
- if (color.alpha === 1) {
257
- label = `'#${toTwoDigitHex(red256)}${toTwoDigitHex(green256)}${toTwoDigitHex(blue256)}`
258
- } else {
259
- label = `'#${toTwoDigitHex(red256)}${toTwoDigitHex(green256)}${toTwoDigitHex(blue256)}${toTwoDigitHex(Math.round(color.alpha * 255))}`
260
- }
261
- result.push({ label: label, textEdit: TextEdit.replace(range, label) })
262
- return result
263
- }
264
-
265
- if (color.alpha === 1) {
266
- label = `rgb(${red256},${green256},${blue256})`
267
- } else {
268
- label = `rgba(${red256},${green256},${blue256},${color.alpha})`
269
- }
270
- result.push({ label: label, textEdit: TextEdit.replace(range, label) })
271
-
272
- if (color.alpha === 1) {
273
- label = `#${toTwoDigitHex(red256)}${toTwoDigitHex(green256)}${toTwoDigitHex(blue256)}`
274
- } else {
275
- label = `#${toTwoDigitHex(red256)}${toTwoDigitHex(green256)}${toTwoDigitHex(blue256)}${toTwoDigitHex(Math.round(color.alpha * 255))}`
276
- }
277
- result.push({ label: label, textEdit: TextEdit.replace(range, label) })
278
-
279
- const hsl = hslFromColor(color)
280
- if (hsl.a === 1) {
281
- label = `hsl(${hsl.h},${Math.round(hsl.s * 100)}%,${Math.round(hsl.l * 100)}%)`
282
- } else {
283
- label = `hsla(${hsl.h},${Math.round(hsl.s * 100)}%,${Math.round(hsl.l * 100)}%,${hsl.a})`
284
- }
285
- result.push({ label: label, textEdit: TextEdit.replace(range, label) })
286
-
287
- // const hwb = hwbFromColor(color);
288
- // if (hwb.a === 1) {
289
- // label = `hwb(${hwb.h} ${Math.round(hwb.w * 100)}% ${Math.round(hwb.b * 100)}%)`;
290
- // } else {
291
- // label = `hwb(${hwb.h} ${Math.round(hwb.w * 100)}% ${Math.round(hwb.b * 100)}% / ${hwb.a})`;
292
- // }
293
- // result.push({ label: label, textEdit: TextEdit.replace(range, label) });
294
-
295
- return result
296
- }
@@ -1,158 +0,0 @@
1
- import {
2
- TextDocuments,
3
- TextDocumentPositionParams,
4
- Hover
5
- } from 'vscode-languageserver/node'
6
- import { Range, TextDocument } from 'vscode-languageserver-textdocument'
7
- import MasterCSS, { render } from '@master/css'
8
- import { css_beautify } from 'js-beautify'
9
-
10
-
11
- export function GetHoverInstance(textDocumentPosition: TextDocumentPositionParams, documents: TextDocuments<TextDocument>) {
12
- const documentUri = textDocumentPosition.textDocument.uri
13
- const language = documentUri.substring(documentUri.lastIndexOf('.') + 1)
14
- const position = textDocumentPosition.position
15
-
16
- const classPattern = /(?:[^"{'\s])+(?=>\s|\b)/g
17
- let classMatch: RegExpExecArray | null
18
-
19
- const document = documents.get(documentUri)
20
-
21
- let instanceRange =
22
- {
23
- start: { line: 0, character: 0 },
24
- end: { line: 0, character: 0 },
25
- }
26
-
27
- const line = document?.getText({
28
- start: { line: position.line, character: 0 },
29
- end: { line: position.line + 1, character: 0 },
30
- })
31
-
32
- let lineText: string = line == null ? '' : line
33
-
34
- const text = document?.getText({
35
- start: { line: 0, character: 0 },
36
- end: { line: position.line, character: position.character },
37
- })
38
-
39
- //#region is in class
40
- const lastClass = text?.lastIndexOf('class') ?? -1
41
- const lastclassName = text?.lastIndexOf('className') ?? -1
42
- const tsxclassName = text?.lastIndexOf('className={') ?? -1
43
-
44
- if (lastClass + lastclassName + tsxclassName == -1) {
45
- return { isInstance: false, instance: '', range: instanceRange, language: language }
46
- }
47
-
48
- const tsxclassNameMode = tsxclassName >= (lastClass > lastclassName ? lastClass : lastclassName)
49
- let textSub = text?.substring(lastClass > lastclassName ? lastClass : lastclassName)
50
- textSub = textSub == null ? '' : textSub
51
-
52
-
53
- let classQuoted = '', classIndexAddOne = '', classIndexAddTwo = ''
54
-
55
-
56
- if (tsxclassNameMode) {
57
- textSub = text?.substring(tsxclassName) == null ? '' : textSub
58
- if (InCurlyBrackets(textSub) == false) {
59
- return { isInstance: false, instance: '', range: instanceRange, language: language }
60
- }
61
- }
62
- else {
63
- if (lastClass > lastclassName) {
64
- classIndexAddOne = textSub.substring(5).trimStart().charAt(0)
65
- classIndexAddTwo = textSub.substring(5).trimStart().substring(1).trimStart().charAt(0)
66
- }
67
- else if (lastClass <= lastclassName) {
68
- classIndexAddOne = textSub.substring(9).trimStart().charAt(0)
69
- classIndexAddTwo = textSub.substring(9).trimStart().substring(1).trimStart().charAt(0)
70
- }
71
- classQuoted = classIndexAddOne + classIndexAddTwo
72
- if (classQuoted != '=\'' && classQuoted != '=`' && classQuoted != '="') {
73
- return { isInstance: false, instance: '', range: instanceRange, language: language }
74
- }
75
- }
76
-
77
- const quotedSingle = textSub.split('\'').length - 1
78
- const quotedDouble = textSub.split('"').length - 1
79
- const quotedTemplate = textSub.split('`').length - 1
80
- if (!tsxclassNameMode) {
81
- if (classQuoted == '=\'' && quotedSingle >= 2) {
82
- return { isInstance: false, instance: '', range: instanceRange, language: language }
83
- }
84
- else if (classQuoted == '="' && quotedDouble >= 2) {
85
- return { isInstance: false, instance: '', range: instanceRange, language: language }
86
- }
87
- else if (classQuoted == '=`' && quotedTemplate >= 2) {
88
- return { isInstance: false, instance: '', range: instanceRange, language: language }
89
- }
90
- }
91
-
92
- if (!((quotedSingle > 0 || quotedDouble > 0 || quotedTemplate > 0) && (quotedSingle % 2 != 0 || quotedDouble % 2 != 0 || quotedTemplate % 2 != 0))) {
93
- return { isInstance: false, instance: '', range: instanceRange, language: language }
94
- }
95
- //#endregion is in class
96
- lineText = lineText.replace('[^\\S\\r\\n]+', ' ')
97
-
98
- let instanceStart = lineText.substring(0, position.character).lastIndexOf(' ')
99
- let instanceEnd = lineText.indexOf(' ', position.character)
100
- instanceEnd = instanceEnd == -1 ? lineText.length - 1 : instanceEnd
101
-
102
- if (tsxclassNameMode) {
103
- instanceStart = instanceStart > lineText.substring(0, position.character).lastIndexOf('{') ? instanceStart : lineText.substring(0, position.character).lastIndexOf('{')
104
- instanceEnd = instanceEnd < lineText.indexOf('}', position.character) ? instanceEnd : (lineText.indexOf('}', position.character)==-1?instanceEnd:lineText.indexOf('}', position.character))
105
- }
106
- else {
107
- instanceStart = instanceStart > lineText.substring(0, position.character).lastIndexOf(classIndexAddTwo) ? instanceStart : lineText.substring(0, position.character).lastIndexOf(classIndexAddTwo)
108
- instanceEnd = instanceEnd > lineText.indexOf(classIndexAddTwo, position.character)
109
- && lineText.indexOf(classIndexAddTwo, position.character) != -1
110
- ? lineText.indexOf(classIndexAddTwo, position.character)
111
- : instanceEnd
112
- }
113
-
114
-
115
- instanceRange = {
116
- start: { line: position.line, character: instanceStart + 1 },
117
- end: { line: position.line, character: instanceEnd },
118
- }
119
- const instance = document?.getText(instanceRange) ?? ''
120
-
121
- return { isInstance: true, instance: instance, range: instanceRange, language: language }
122
- }
123
- function InCurlyBrackets(text: string): boolean {
124
- let curlybrackets = 0
125
- for (let i = 0; i < text.length; i++) {
126
- if (text.charAt(i) == '{') {
127
- curlybrackets += 1
128
- }
129
- else if (text.charAt(i) == '}') {
130
- curlybrackets -= 1
131
- if (curlybrackets <= 0) {
132
- return false
133
- }
134
- }
135
- }
136
- if (curlybrackets <= 0) {
137
- return false
138
- }
139
- return true
140
- }
141
-
142
- export function doHover(instance: string, range: Range, masterCss: MasterCSS = new MasterCSS()): Hover | null {
143
- const renderText = render(instance.split(' '), masterCss)
144
- if (!renderText || renderText == ' ') {
145
- return null
146
- }
147
-
148
- return {
149
- contents: {
150
- language: 'css',
151
- value: css_beautify(renderText, {
152
- newline_between_rules: true,
153
- end_with_newline: true
154
- })
155
- },
156
- range: range
157
- }
158
- }
package/src/masterCss.ts DELETED
@@ -1,80 +0,0 @@
1
- import {
2
- TextDocuments,
3
- Position,
4
- } from 'vscode-languageserver/node'
5
- import { Range, TextDocument } from 'vscode-languageserver-textdocument'
6
- import { instancePattern } from './utils/regex'
7
-
8
- export function PositionCheck(documentUri: string, position: Position, documents: TextDocuments<TextDocument>, RegExpList: string[]) {
9
- const result: {
10
- IsMatch: boolean,
11
- PositionIndex: number,
12
- classStartIndex: number,
13
- classEndIndex: number,
14
- classString: string,
15
- instance: { range: Range, instanceString: string },
16
- instanceList: { range: Range, instanceString: string }[],
17
- } = {
18
- IsMatch: false,
19
- PositionIndex: 0,
20
- classStartIndex: 0,
21
- classEndIndex: 0,
22
- classString: '',
23
- instance: { range: { start: Position.create(0, 0), end: Position.create(0, 0) }, instanceString: '' },
24
- instanceList: [],
25
- }
26
-
27
- const document = documents.get(documentUri)
28
- let text = document?.getText() ?? ''
29
- const positionIndex = document?.offsetAt(position) ?? 0
30
-
31
- const startIndex = document?.offsetAt({ line: position.line - 100, character: 0}) ?? 0
32
- const endIndex = document?.offsetAt({ line: position.line + 100, character: 0 }) ?? undefined
33
- text = text.substring(startIndex, endIndex)
34
-
35
- let instanceMatch: RegExpExecArray | null
36
- let classMatch: RegExpExecArray | null
37
-
38
- result.PositionIndex = positionIndex
39
-
40
- RegExpList.forEach(x => {
41
- const classPattern = new RegExp(x, 'g')
42
-
43
- while ((classMatch = classPattern.exec(text)) !== null) {
44
- if ((classMatch.index <= positionIndex && classMatch.index + classMatch[0].length - 1 >= positionIndex) == true) {
45
- result.IsMatch = true
46
- result.PositionIndex = positionIndex
47
- result.classStartIndex = classMatch.index
48
- result.classEndIndex = classMatch.index + classMatch[0].length - 1
49
- result.classString = classMatch[0]
50
-
51
- while ((instanceMatch = instancePattern.exec(classMatch[2])) !== null) {
52
- result.instanceList.push(
53
- {
54
- range: {
55
- start: document?.positionAt(classMatch.index + classMatch[1].length + instanceMatch.index) ?? Position.create(0, 0),
56
- end: document?.positionAt(classMatch.index + classMatch[1].length + instanceMatch.index + instanceMatch[0].length) ?? Position.create(0, 0)
57
- },
58
- instanceString: instanceMatch[0]
59
- }
60
- )
61
- if ((classMatch.index + classMatch[1].length + instanceMatch.index <= positionIndex && classMatch.index + classMatch[1].length + instanceMatch.index + instanceMatch[0].length >= positionIndex) == true) {
62
- result.instance = {
63
- range: {
64
- start: document?.positionAt(classMatch.index + classMatch[1].length + instanceMatch.index) ?? Position.create(0, 0),
65
- end: document?.positionAt(classMatch.index + classMatch[1].length + instanceMatch.index + instanceMatch[0].length) ?? Position.create(0, 0)
66
- },
67
- instanceString: instanceMatch[0]
68
- }
69
- }
70
- }
71
-
72
- return result
73
- }
74
- else if (classMatch.index > positionIndex) {
75
- break
76
- }
77
- }
78
- })
79
- return result
80
- }